Ранее было рассмотрено использование событий для взаимодействия с пользователем. Но как обрабатывать события элементов, которые размещены в FXML? Для этого нам нужны специальные сущности - контроллеры.
По сути контроллер это обычный класс java, который может взамодействовать с FXML. Итак, определим файл MainController.java со следующим содержимым:
import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; public class MainController { @FXML private Button btn; @FXML private void click(ActionEvent event) { btn.setText("You've clicked!"); } }
Здесь определена кнопка, а также метод, который соответствует определению метода handle интерфейса EventHandler. То есть метод click в данном случае будет выступать в качестве обработчика нажатия кнопки, изменяя ее текст.
Важно отметить наличие аннотации @FXML
, которая позволяет сопоставить переменные и методы в контроллере с сущностями в FXML.
Далее определим следующий файл Main.fxml:
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.scene.Group?> <?import javafx.scene.control.Button?> <Group fx:id="root" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MainController"> <Button text="Click!" onAction="#click" fx:id="btn" /> </Group>
Как и в прошлой теме, интерфейс представлен элементом Group, который содержит элемент Button. Но есть ряд изменений. Прежде всего в корневом узле (в данном случае элементе Group) подключается пространство имен XML, которое содержит нужную нам функциональность, в частности, определение атрибута id:
xmlns:fx="http://javafx.com/fxml/1"
Пространства имен XML могут содержать функционал, который по умолчанию недоступен и который мы хотим использовать. При подключении пространств имен XML после
xmlns:
указывает префикс, с которым будет сопоставляться подключенное пространство. Например, в данном случае мы сможем обратиться к
функциональности этого пространства через префикс fx.
Далее с помощью атрибута fx:controller в корневом узле устанавливается класс контроллера который должен использоваться, то есть в данном случае MainController. Причем перед атрибутом используется префикс fx, поскольку атрибут controller определен в пространстве имен "http://javafx.com/fxml/1".
Кроме того, мы можем использовать специальный атрибут fx:id
, который также определен в "http://javafx.com/fxml/1" и который устанавливает
идентификатор элемента. Через идентификатор мы можем обращаться к этому элементу из контроллера.
Стоит отметить, что идентификатор кнопки соответствует имени переменной в классе контроллера: btn
, благодаря этому мы можем связать
элемент из FXML и переменную в контроллере.
Второй момент, который надо отметить: у класса Button есть свойство onAction, которое хранит обработчик события нажатия в виде объекта
EventHandler<ActionEvent>
. В FXML мы также можем установить это свойство с помощью одноименного атрибута. В качестве значения ему передается метод
из контроллера - в нашем случае метод click
. Опять же между названием метода в контроллере и значением атрибута в FXML должно быть соответствие по имени за тем
исключением, что в FXML перед названием метода ставится знак решетки (onAction="#click"
).
Таким образом класс контроллера и интерфейс FXML могут взамодействовать.
И в файле Main.java главный класс программы будет загружать интерфейс из Main.fxml:
import javafx.application.Application; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; public class Main extends Application{ public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("Main.fxml")); Scene scene = new Scene(root); stage.setScene(scene); stage.setTitle("Hello JavaFX"); stage.setWidth(250); stage.setHeight(200); stage.show(); } }
То есть в одной папке проекта у нас будут три файла:
MainController.java
Main.java
Main.fxml
В конце нам надо скомпилировать все классы проекта и запустить главный класс:
И нажатия на кнопку будут обрабатываться: