Свойства и привязки
В JavaFX почти каждое значение элемента — текст поля, отметка флажка, доступность кнопки — хранится в свойстве (property). Свойство — это обёртка над значением, которая сообщает всем подписчикам, что значение изменилось. Благодаря этому одно значение можно привязать к другому, и JavaFX будет обновлять его сам.
Свойства элементов
У каждого свойства есть метод с окончанием Property:
| Значение | Обычный метод | Свойство |
|---|---|---|
| Текст поля | getText() | textProperty() |
| Отметка флажка | isSelected() | selectedProperty() |
| Кнопка отключена | isDisable() | disableProperty() |
| Длина текста | getLength() | lengthProperty() |
Слушатель изменений
К свойству можно подключить слушатель — лямбду с тремя параметрами: само свойство, старое и новое значение:
// src/main/java/com/example/notes/App.java — фрагмент start()
importantBox.selectedProperty().addListener((observable, oldValue, newValue) ->
System.out.println("Важная: " + oldValue + " -> " + newValue));Отметьте флажок — в терминале появится Важная: false -> true.
Привязка
bind связывает свойство с другим значением навсегда: когда источник меняется, меняется и привязанное свойство. Покажем под текстом заметки счётчик символов:
// src/main/java/com/example/notes/App.java — фрагмент start()
Label charsLabel = new Label();
charsLabel.textProperty().bind(textArea.lengthProperty().asString("Символов: %d"));asString превращает число в строку по шаблону, как String.format. Надпись обновляется с каждой набранной буквой. Добавьте её в сетку: form.add(charsLabel, 1, 4).
Кнопка без if
Привязки умеют вычислять условия. Кнопка «Добавить» будет недоступна, пока заголовок пуст:
// src/main/java/com/example/notes/App.java — фрагмент start()
addButton.disableProperty().bind(titleField.textProperty().isEmpty());isEmpty() возвращает не boolean, а привязку BooleanBinding, которая пересчитывается при каждом изменении текста. Есть и другие: isNotEmpty(), isNull(), greaterThan(), and(), not().
Своё свойство
Свойство можно создать и для своих данных. Посчитаем добавленные заметки:
// src/main/java/com/example/notes/App.java — фрагмент
private final IntegerProperty count = new SimpleIntegerProperty(0);
// в start():
Label countLabel = new Label();
countLabel.textProperty().bind(count.asString("Заметок: %d"));
// в addNote():
count.set(count.get() + 1);countLabel поставьте в левую панель вместо надписи «Заметок пока нет»: new VBox(countLabel). Обработчик меняет только число, а текст надписи обновляется сам.
Для других типов есть SimpleStringProperty, SimpleBooleanProperty, SimpleDoubleProperty и SimpleObjectProperty.
Проверка
Запустите приложение. Слева — «Заметок: 0», кнопка «Добавить» серая. Введите заголовок — кнопка станет доступной. Нажмите её дважды с разными заголовками — слева будет «Заметок: 2». Наберите в тексте «Привет» — под флажком появится «Символов: 6».
Частая ошибка
Привязанному свойству нельзя присвоить значение вручную. Если после charsLabel.textProperty().bind(...) вызвать charsLabel.setText("..."), программа упадёт с java.lang.RuntimeException: Label.text : A bound value cannot be set. Сначала снимите привязку методом unbind() или меняйте источник. Для связи в обе стороны, например поле и свойство модели, используют bindBidirectional.