Взаимодействие пользователя и интерфейса

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

Для реакции на события используются слушатели. Концепция: в программе есть несколько источников событий (Dispatchers) (кнопок, полей ввода, мыши и т.п.) Они генерируют события (Event), у событий есть свойства (дополнительная информация), например, у события, что пользователь подвинул мышь, есть свойства координат курсора. У события “выбор элемента в списке” есть свойство — индекс выбранного элемента. Слушатели — реагируют на события. Для этого они регистрируются у источников событий и просят их уведомлять их о событиях. При регистрации слушатель указывает, какие именно события ему интересны.

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

Значения, за которыми можно наблюдать

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

Изменение обычного значения типа int

int x = 42;
//...
x = 56; //может ли кто-то отреагировать на изменение?

Observable — значения, за изменением которых можно наблюдать.

// SimpleIntegerProperty - является ObservableIntegerValue

SimpleIntegerProperty x = new SimpleIntegerProperty(42);
//1 вид слушателей, узнают только о новом значении
x.addListener(observable ->
        System.out.println("значение переменной x изменилось на " + x)
);
//2 вид слушателя, знает и старое значение до изменения тоже
x.addListener((observable, oldValue, newValue) -> // здесь всегда observable == x
        System.out.println("Значение x изменилось с " + oldValue + " на " + newValue)
);
x.set(56); //в этот момент сработает слушатель

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

Пример. Программа с обработкой событий: JavaFXExampleSeveralPanels