Статьи

Построение реактивных систем с JavaFX

реагировать JavaFX — это новая стандартная библиотека для создания графических приложений на Java, но многие программисты все еще придерживаются Swing или даже (дрожат) AWT. Многое произошло за 20 лет существования Java. Когда два года назад я начал искать библиотеки JavaFX для пользовательского интерфейса Speedment, я обнаружил, что многие вещи увлекательны! Вот несколько советов о том, как вы можете использовать многие новые замечательные функции в наборе инструментов JavaFX для создания быстрых и быстрых приложений!

1. Стоимость недвижимости

Если вы слонялись по компонентам JavaFX, вы наверняка встречали термин Property. Можно наблюдать почти каждое значение в библиотеке FX, ширину разделителя, размер изображения, текст в метке, дочерние элементы списка, а также статус флажка. Свойства бывают двух категорий; Письменные и читаемые. Записываемое значение может быть изменено либо с помощью установщика, либо путем прямого изменения свойства. JavaFX будет обрабатывать события и будет уведомлять каждый компонент, который зависит от свойства. У читаемого значения есть методы, которые позволяют вам получать уведомления при изменении значения.

Пример:

1
2
3
4
// Read- and writable
StringProperty name = new SimpleStringProperty("Emil");
// Only readable
ObservableBooleanValue nameIsEmpty = name.isEmpty();

2. Связующие значения

Когда у вас есть доступное для записи и читаемое значение, вы можете приступить к определению правил для того, как эти значения связаны. Записываемое свойство может быть связано с читаемым свойством, так что его значение всегда будет совпадать с читаемым. Привязки не являются немедленными, но они будут разрешены до того, как будут соблюдены значения (посмотрите, что я там делал). Привязки могут быть однонаправленными или двунаправленными. Конечно, если они двунаправлены, оба свойства должны быть доступны для записи.

Пример:

1
2
3
TextField fieldA = new TextField();
TextField fieldB = new TextField();
fieldA.prefWidthProperty().bind(fieldB.widthProperty());

3. Наблюдаемые списки

Свойства не единственное, что можно наблюдать. Члены списка также можно наблюдать, если список заключен в ObservableList . Модель реакции ObservableList довольно продвинута. Вы можете не только получить уведомление об изменении списка, но и узнать, как именно этот список был изменен.

Пример:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
List<String> otherList = Arrays.asList("foo", "bar", "bar");
ObservableList<String> list = FXCollections.observableList(otherList);
 
list.addListener((ListChangeListener.Change<? extends String> change) -> {
    System.out.println("Received event.");
    while (change.next()) {
        if (change.wasAdded()) {
            System.out.println(
                "Items " + change.getAddedSubList() + " was added.");
        }
 
        if (change.wasRemoved()) {
            System.out.println(
                "Items " + change.getRemoved() + " was removed.");
        }
    }
});
 
System.out.println("Old list: " + list);
list.set(1, "foo");
System.out.println("New list: " + list);

Выход из вышесказанного:

1
2
3
4
5
Old list: [foo, bar, bar]
Received event.
Items [foo] was added.
Items [bar] was removed.
New list: [foo, foo, bar]

Как видите, операция set создала только одно событие.

4. StringConverter

Иногда вы обнаружите, что у вас нет точного значения в компоненте, так как вам нужно создать привязку. Типичным примером этого является то, что у вас есть StringProperty с путем, который вы получили из TextField. Если вы хотите, чтобы наблюдаемое свойство имело это значение, выраженное как путь, вам необходимо создать для этого StringConverter.

Пример:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
TextField fileLocation = new TextField();
StringProperty location = fileLocation.textProperty();
Property<Path> path = new SimpleObjectProperty<>();
 
Bindings.bindBidirectional(location, path, new StringConverter<Path>() {
    @Override
    public String toString(Path path) {
        return path.toString();
    }
 
    @Override
    public Path fromString(String string) {
        return Paths.get(string);
    }
});

Свойство объекта не связано двунаправленно со значением текстового поля.

5. Выражения

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

Пример:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
TextField first  = new TextField();
TextField second = new TextField();
TextField mix    = new TextField();
 
mix.textProperty().bind(
    Bindings.when(
        first.lengthProperty().isEqualTo(second.lengthProperty())
    ).then(Bindings.createStringBinding(
        () -> {
            int length        = first.lengthProperty().get();
            String firstText  = first.textProperty().get();
            String secondText = second.textProperty().get();
            char[] result     = new char[length * 2];
 
            for (int i = 0; i < length; i++) {
                result[i * 2]     = firstText.charAt(i);
                result[i * 2 + 1] = secondText.charAt(i);
            }
 
            return new String(result);
        },
        first.textProperty(),
        second.textProperty()
    )).otherwise("Please enter two strings of exactly the same length.")
);

Вывод

Это были лишь немногие из множества функций JavaFX. Надеюсь, вы сможете найти еще больше креативных способов использования системы событий!

Ссылка: Создание реактивных систем с JavaFX от нашего партнера JCG Эмиля Форслунда из блога Age of Java .