Способы передачи параметров в Java

👁 148 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Как известно, в Java нет отдельных функций, как в С++/C/PHP/…, все реализуется в пределах класса и бывает случаи, когда необходимо передавать параметры методу или конструкции по умолчанию, или переменное количество параметров. В данной статье рассмотрим несколько способов реализации передачи необязательных параметров.

1.Способ перегрузки

void foo(String a,Integer b){//...}
void foo(String a){
foo(a,0);// где, 0 является необязательным параметром для b
}
foo("a",2); foo("a");

Одним из ограничений такого подхода является то, что он не работает, если у вас есть два необязательных параметра одного и того же типа и любой из них может быть опущен.

2. Использование Varargs

a) Все необязательные параметры имеют одинаковые типы:

void foo(String a, Integer... b){
  Integer b1 = b.length >0? b[0]:0;
  Integer b2 = b.length >1? b[1]:0;
  //...
  }
  foo("a");
  foo("a", 1, 2);

b) Типы необязательных параметров различные:

void foo(String a,Object... b){
     Integer b1 =0;
     String b2 ="";
     if(b.length >0){
        if(!(b[0] instanceof Integer)){
          throw new IllegalArgumentException("...");
        }
        b1 =(Integer)b[0];
     }
     if(b.length > 1){
       if(!(b[1] instanceof String)){
         throw new IllegalArgumentException("...");
       }
       b2 =(String)b[1];
       //...
     }
     //...
}  

foo("a");
foo("a",1);
foo("a",1,"b2");

Главный недостаток данного подхода — то, что необязательные параметры имеют различные типы и этим вы теряете статическую проверку типов. Кроме того, если каждый параметр имеет различные значения, то необходимо каким-то образом различить их.

3. Проверка на NULL

Для устранения ограничения передачи по типу можно использовать другой подход — проверка на передача значения на null и внутри тела функции организовать проверку : если передано null, то установить значения по умолчанию

void foo(String a,Integer b,Integer c){ 
         b = b !=null? b :0; 
         c = c !=null? c :0;
         //...
      }  
      foo("a",null,2);

Теперь все значения всех аргументов должны быть определены, но по умолчанию можно установить и как null.

4. Передача необязательного класса

Этот подход аналогичен предыдущему подходу, но использует guava необязательный класс в виде параметра, который имеет значения по умолчанию

void foo(String a,Optional bOpt){
         Integer b = bOpt.isPresent()? bOpt.get():0;
         //...
   }

   foo("a",Optional.of(2));
   foo("a",Optional.absent());

5.Использование шаблона Builder

Шаблон Builder используется для конструкторов и реализуется путем введения отдельного класса Builder

class Foo{
     privatefinalString a;
     privatefinalInteger b;
     Foo(String a,Integer b){
       this.a = a;
       this.b = b;
     }
     //...
}
class FooBuilder{
    privateString a ="";
    privateInteger b =0;
    FooBuilder setA(String a){
     this.a = a;
     return this;
    }
    FooBuilder setB(Integer b){
      this.b = b;
      return this;
    }
    Foo build(){returnnewFoo(a, b);
  }
}
Foo foo =new FooBuilder().setA("a").build();

6. Использование карт Maps

Когда количество параметров слишком большое и для большинство из них используют значения по умолчанию, то вы можете получить аргументы метода в виде карты, как имя/значение

void foo(Map<String,Object> parameters){
        String a ="";
        Integer b =0;
        if(parameters.containsKey("a")){
        if(!(parameters.get("a") instanceof Integer)){
           throw new IllegalArgumentException("...");
        }
        a =(String)parameters.get("a");
    }
    if(parameters.containsKey("b")){
     //... 
    }
     //...
}
foo(ImmutableMap.<String, Object>of("a", "a", "b", 2, "d", "value"));

 

Класс Stage в JavaFX

👁 177 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

В данной статье попытаемся разобраться с классом Stage в JavaFX. Понимание принципа работы данного класса очень важно, так как это один из главных классов, который вплотную работает с графами(контролами JavaFX). Публичный класс Stage расширяет класс Window. 

Замечание. Так как, данное слово имеет множество омонимов, то мне так и не удалось ясно представить суть значения этого слова с английского на русский, но кандидатами могут быть следующие значения: этап, стадия, ступень, платформа. Но больше всего подходит платформа, на котором, в дальнейшем, строятся различные сцены с помощью класса Scene.

public class Stage extends Window

Класс Stage в JavaFX является верхнеуровневым контейнером.  Основной Stage конструирует платформу. В приложении могут быть сконструированы дополнительные платформы на основе Stage. Объект Stage должен быть сконструирован и модифицирован на основе потока JavaFX приложения. Большинство свойств данного класса предназначены только для чтения, потому что они могут быть изменены извне базовой платформы и, следовательно, не могут быть связанными.

Стили Stage

Stage платформа может иметь один из следующих стилей, которые являются статическими свойствами класса  StageStyle:

  • StageStyle.DECORATEDStage со сплошным белым задним фоном и стилизацией платформы;
  • StageStyle.UNDECORATED — Stage со сплошным белым задним фоном и без стилизацией платформы;
  • StageStyle.TRANSPARENT — Stage с прозрачным задним фоном и без стилизации платформы;
  • StageStyle.UTILITY — Stage со сплошным белым задним фоном и с минимальной стилизацией платформы;

Стили должны быть инициализированы перед тем, как платформа может быть выведена на экран с помощью метода show().  На некоторых платформах стилизации могут быть недоступны. К примеру, на некоторых мобильных или встраиваемых устройствах. В таких случаях запросы DECORATED или UTILITY окна могут быть установлены, но стили не будут показаны.

Родитель Stage

Платформа может дополнительно иметь собственные окна. Когда окно является владельцем платформ, то это как бы говорит, что оно является родителем для этих платформ. Когда закрыто родительское окно, то все его потомки будут также закрыты. Платформа должна всегда находиться поверх ее родительского окна. Владелец должен быть инициализирован перед платформой, которая выводиться.

Модальность

Платформа имеет один из следующих модальностей:

  • Modality.NONE — платформа, которая не блокируется никаким другим окном;
  • Modality.WINDOW_MODAL — платформа, которую блокируют входные события, распространяемые от источника ко всем окнам из его родителя к его корню. Этот корень является ближайшим предком окна без родителя;
  • Modality.APPLICATION_MODAL — платформа, которую блокируют входные события, распространяемые от того же приложения, исключая для тех которые исходят из его иерархии потомков;

Когда окно блокировано модальной платформой Stage его Z-порядок по отношению к потомкам сохраняется и он не получает никаких событий и никаких событий активации окна, но продолжает анимировать и нормально визуализировать. Необходимо заметить, что показываемая модальная платформа не обязательно блокирует его вызвавший родитель.  Метод show() возвращает вывод непосредственно и независимо от модальности платформы.  Если необходимо блокировать родитель, вызвавший платформу Stage до скрытия или закрытия платформы, то необходимо использовать showAndWait().  Модальное окно может быть инициализировано перед тем, как платформа может быть выведена(показана).

Пример использования Stage

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class HelloWorld extends Application {

    @Override public void start(Stage stage) {
        Text text = new Text(10, 40, "Hello World!");
        text.setFont(new Font(40));
        Scene scene = new Scene(new Group(text));

        stage.setTitle("Welcome to JavaFX!"); 
        stage.setScene(scene); 
        stage.sizeToScene(); 
        stage.show(); 
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

 

Способы реализации функции (callback) функции обратного вызова в Java

👁 289 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Callback — функция обратного вызова. Используется тогда, когда необходимо выполнить определенный кусок кода, передав данный кусок кода в виде параметра методу и, естественно, данный кусок будет исполняться внутри переданного метода. Чтобы передать данный кусок кода, нам необходимо это кусок кода как-то именовать, естественно, что в Java мы будет это организовать в виде метода и будем передавать этот метод в виде аргумента другим методам.

Когда и где это может быть использовано?

Для начала, рассмотрим задачу вывода диалогового окна, средствами JavaFX. Так как JavaFX не содержит в арсенале понятие диалоговое окно, то нам придется его создавать самим. Такое окно может выводить любую информацию в виде элемента управления или просто текста. Нам необходимо как-то обработать события, которые расположены на данном диалоговом окне. Для решения данной задачи, сначала, воспользуемся решением без использования callback

public class Dialog {
    /** Интерфейс для обработки события*/
    public static String result = null;//Создадим поле хранения текущего значения
      
    public static void setResult(String result)//Реализуем setter
    {
        Dialog.result = result;
    }
    public static String getResult()//Реализуем getter
    {
        return Dialog.result;
    }

    //Метод реализации вывода диалогового окна
    public static void showAlert(String title){

          //Создаем новый экземпляр стадии(будет выполняться наряду с основным потоком программы)
          final Stage dlgStage = new Stage();

          //Создадим кнопку
          Button btnOk = new Button("Ok");
          
          //Прикрепим к кнопке событие
          btnOk.setOnAction(new EventHandler(){
              @Override
              public void handle(ActionEvent arg0) {
                  setResult("Yo click Ok!");//Устанавливаем значение при нажатии на кнопку
                  dlgStage.close();//Закрываем диалоговое окно при нажатии
              }
          });

          //Текстовое поле для вывода информации
          Label lblTitle = new Label(title);
          lblTitle.setFont(Font.font("Amble CN", FontWeight.NORMAL, 14));

          //Создаем контейнер для вертикального выравнивания элементов
          VBox vbox = new VBox(lblTitle,btnOk);
          vbox.setAlignment(Pos.CENTER);
          vbox.setMinSize(300, 200);

          //Создаем новую сцену и передаем ей контейнер
          Scene dlgScene = new Scene(vbox);

          //Устанавливаем сцену, инициализировав стили и т.д.
          dlgStage.setScene(dlgScene);
          dlgStage.initStyle(StageStyle.UNDECORATED);
          dlgStage.initModality(Modality.APPLICATION_MODAL);
          dlgStage.setMinWidth(300);
          dlgStage.setMinHeight(200);
          dlgStage.show();      
  }
}

Наш класс реализации диалогового окна готов, настал момент вывести его на экран, написав следующий код

Dialog.showAlert("Hello world!");
if(Dialog.getResult() != null)
{
  System.out.println(Dialog.getResult());// Результат, записанный при нажатии
}

В результате мы получим следующий результат на экране

java-dialog-callback

Нажмем на кнопку и посмотрим на вывод в консоле NetBeans, где у нас ничего не выведется в первый раз, потому что диалоговое окно выполняется своим потоком, а программа своим и после нажатия на «ok» мы инициализируем значение поля result, закрываем диалоговое окно, но повторно — то этот код не выпонится, поэтому значение в result при первом запуске будет null, как мы его инициализировали в классе Dialog. При повторном выполнении данного кода у нас выведется тоже самое окно, но значение уже будет не текущее, а предыдущего нажатия, что не есть нормально, так как создается 2 потока: 1- поток программы, 2 — поток диалогового окна.

 Решение проблемы с помощью callback

Код ниже именуется как callback.

new EventHandler<ActionEvent>(){
    @Override 
    public void handle(ActionEvent arg0){    
    dlgStage.close();
  }
}

Callback не возвращает type, как вы можете видеть выше в примере, он void.

Callback — и имеют методы, которые вы получаете как аргументы в другом методе.  Другой метод должен вызвать callback метод, когда он пожелает. Это значит, что callback — и имеют асинхронность.

В вашем примере, он вызывает callback, когда вы жмете на кнопку.

И в заключении, вы не сможете возвратить его, используя return.

Что делать ?

Вы можете вызвать метод из вашего callback и отправить ваше возвращаемое значение ему как аргумент.

Пример:

btnCancel.setOnAction( newEventHandler<ActionEvent>(){
    @Override
    public void handle(ActionEvent arg0){

        YourClass.setReturnValue("This is button Cancel");
        dlgStage.close();
   }
 });

Где setReturnValue  -метод принадлежащий вашему классу YourClass или его экземпляр, который будет содержать ваше возвращаемое значение.

Другой и лучшим путем подхода будет создание класса, который будет наследовать Stage. Также в вашем  showPrompt методе вы должны блокировать выполнение основного потока, используя showAndWait() или похожим образом.

В заключении, вы не можете создавать весь Prompt из только одного метода.

Работа с обработчиками событий в JavaFX

👁 195 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Данная статья расскажет вам как работать с обработчиками событий в JavaFX программах. Вы узнаете как можно обработать событие, которое было сгенерировано клавиатурой, мышью, скролами и другими элементами управления на экране вашего JavaFX приложения 🙂 .

Обработчики событий позволяют вам обрабатывать события на этапе восходящей фазы. Каждый узел может иметь один или более обработчиков для обрабатываемого события.  Простой обработчик может использовать один или более узлов и более одного типов событий. Если обработчик события для дочернего узла не использует событие, обработчик события для родительского узла позволяет родительскому узлу действовать на события после процесса дочернего узла, обрабатывать их и обеспечить общую обработку событий для нескольких дочерних узлов.

Регистрация и удаление обработчика события для узла

Для обработки события на этапе восходящей фазы узел должен зарегистрировать обработчик. Обработчик события наследует интерфейс EventHandler. Метод handle() данного интерфейса предоставляет код, который будет выполнен, когда событие, которое ассоциировано с обработчиком получит узел,для которого зарегистрирован обработчик.

Для регистрации обработчика используется метод addEventHandler(). Данный метод получает тип события и обработчик в виде аргумента. Ниже представлен пример , где первый обработчик добавляется к простому узлу и обрабатывается определенный тип события. Второй обработчик — для обработки события ввода, определен и зарегистрирован для 2-х различных узлов. Обработчик также зарегистрирован для двух различных типов событий.

//Пример регистрации обработчика для одного узла определенного типа события
node.addEventHandler(DragEvent.DRAG_ENTERED, 
                    new EventHandler() {
                        public void handle(DragEvent) { ... };
                    });

//Определение обработчика для предыдущего события
EventHandler handler = new EventHandler(() {
    public void handle(InputEvent event) {
        System.out.println("Handling event " + event.getEventType()); 
        event.consume();
    }

//Регистрация одного обработчика для двух различных узлов
myNode1.addEventHandler(DragEvent.DRAG_EXITED, handler);
myNode2.addEventHandler(DragEvent.DRAG_EXITED, handler);

//Регистрация еще одного типа события для первого из двух различных узлов
myNode1.addEventHandler(MouseEvent.MOUSE_DRAGGED, handler);

Обратите внимание, что обработчик события, который определен для одного типа события также может быть использован в любых подтипах этого события. Для глубокого анализа можете прочесть официальную статью Oracle, где описывается иерархия типов событий.

Когда вам больше не нужен обработчик события для узла, то его можно удалить, используя метод  removeEventHandler(). Данный метод в виде параметров получает тип удаляемого события и его обработчик. В ниже следующем примере представлен код, который демонстрирует данную возможность, где удаляется событие DragEvent.DRAG_EXITED узла myNode1 из предыдущего примера, но обработчик еще выполняет данный тип события для узла myNode2, и событие MouseEvent.MOUSE_DRAGGED для узла myNode1.

//Удаляем событие обработчика
myNode1.removeEventHandler(DragEvent.DRAG_EXITED, handler);

 Совет: Для удобства удаления обработчика события достаточно передать значение null в виде параметра через специальный метод, к примеру node1.setOnMouseDragged(null).

 

Архитектура JavaFX

👁 126 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

В данной статье будет рассмотрена архитектура приложений JavaFX.  JavaFX является надслойкой виртуальной машины JVM и включает в себя целый набор утилит и модулей для полноценной работы с 2D/3D графикой, с представлениями окон, медиа — контентом, WEB — контентом, а также предоставляет программные инструменты для взаимодействия между, вышеперечисленными, компонентами. Ниже представлена иллюстрация того, как устроена надслойка JavaFX

Архитектура JavaFX

 

Графы сцены

Графы сцены или Scene Graph  — это самый верхний слой в архитектуре JavaFX. Он представлен иерархической структурой узлов и является начальной точкой построения визуального приложения JavFX, который включает в себя различные визуальные элементы управления. Данный слой управляет вводом и выводом данных начальных и конечных данных от пользователя. Графа сцены представлен набором узлов, которые имеют атрибуты такие как ID(уникальный идентификатор узла), который необходим для идентификации элемента управления в Java или CSS коде, class(используется, как правило при придании различных стилевых свойств атрибутов через CSS) и др., а также представлен определенным, ограниченным размером в пределах экрана монитора. За исключением корневого элемента или как его еще называют root node, каждый узел имеет свой родительский элемент и 0 или более дочерних узлов, которым можно придать следующие атрибуты:

  • Эффекты, такие как мутность и тень;
  • Прозрачность;
  • Трансформации;
  • Обработчики событий мыши, клавиатуры, внутренних методов в коде Java;
  • Специфичных для приложения различные состояния отображения;

В отличии от Swing и AWT(Abstract Window Toolkit) , JavaFX включает в себя еще графические примитивы такие как линии, прямоугольники, окружности и т.д., которые можно использовать наряду с остальными элементами управления и в дополнении имеет контейнеры, элементы для просмотра изображений и проигрывания медиа-контента.

JavaFX предоставляет богатые возможности для графов через javafx.animation API, который способен добавлять различные динамические спецэффекты и анимации.

JavaFX API позволяет создавать контент, специфичный для нескольких типов:

  • Узлы: Сущности (2-D и 3-D), изображения, медиа, встроенный WEB браузер, текст, UI элементы, графики, группы и другие контейнеры;
  • Состояние: Трансформации (позиции и ориентации узлов), визуальные эффекты и другие визуальные состояния;
  • Эффекты: Простые объекты, которые меняют свой внешний вид, обретая эффекты замутнения, тени и цветовых установок;

 Публичный открытый API для JavaFX

Верхний слой JavaFX архитектуры, показанный на вышеприведенной картинке, предоставляет законченный, публичный API, который поддерживает построение богатых возможностями клиентских приложений. Данный API предоставляет не параллельную, свободную и гибкую возможность для построения богатые клиентскими возможностями приложения. В JavaFX скомбинорованы лучшие возможности Java платформы со всесторонним погружением в медиа-функционал. Java для JavaFX характеризует:

  • Позволяет использовать полноценные Java характеристики , такие как генераторы, аннотации, многопоточность и лямбда выражения(включенные в Java SE 8);
  • Делает разработку для WEB очень легкой и позволяет для этого использовать другие, базовые для JVM, языки, такие как Groovy и JavaScript;
  • Позволяет разработчикам использовать другие системные языки, такие как Groovy для написания больших комплексных и сложных JavaFX приложений;
  • Позволяет использовать связывание, которое включают поддержку для высокопроизводительных lazy binding, binding выражения, bound sequence выражения и частичное связывание;
  • Внешние Java коллекции библиотек включают наблюдаемые списки(observable lists) и карты, которые позволяют программам соединять пользовательский интерфейс к моделям данных, позволяя наблюдать за обновлением или изменением данных в этих моделях и обновлением или изменением вместе с этим данных в пользовательских элементах управления;

JavaFX API и и программная модель имеет продолжение от JavaFX 1.x линейки выпуска, поэтому старые проекты можно легко перенести на новый выпуск JavaFX 2.x без особых затруднений.