[Java] JavaFX: класс Controller и fx:id в FXML
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Мне кажется, не оправданно много полезных статей не только не посвящают и двух слов самому животрепещущему вопросу при начале работы с JavaFX, но и посвятив, все равно не раскрывают его полностью. А вопрос возникает следующий: как наладить связь ваших node по их fx:id и вашего кода. Как использовать их в разных частях кода, чтобы ссылаться на ваш программный интерфейс? Вот на это, я и постараюсь ответить под катом
Что такое fx:id и с чем его едят
По какой-то причине, для авторов статей и комментаторов на StackOverFlow не очевидно, что попросту не понятно для читателя, как происходит связь fx:id ссылок с вашим кодом. Потому что это не очевидно. А некоторые моменты, вообще больше похожи на магию, этот момент я отдельно упомяну ниже.
Вообще, многие статьи полезны, информативны (особенно на английском), так же, есть ответы почти на все на StackOverFlow. Но, практически нигде развернуто не сказано, как именно работать с fx:id, которые мы определяем в FXML файле. Лишь краткие упоминания, которые приводят к еще большей путанице в голове. Обычно пишут "задайте вашей node нужный вам fx:id и будем вам счастье".
К сожалению, счастья не будет. Будет NullPointerException. По причине некорректного использования, которое идет из непонимания области видимости, скажем так, этих id. И я хочу рассказать, по какой причине получается exception, а главное, как корректно связать ваш FXML с классом-контроллером и java-кодом. Надеюсь, это поможет людям избежать тех мучений, которые прошел я в поисках ответа на данный вопрос.
Я бы наверно и пришел к ответу сам, рано или поздно, но спустя многие часы дни поиска, я наткнулся на статью. В ней рассказано про MVC модель, которую и следует использовать при разработке на JavaFX. Не стану повторять написанное в статье, там достаточное описание этой модели. Если вы о ней не слышали, то к прочтению обязательно, поскольку можно обойтись работая с javaFX вообще без FXML, на чистом java коде, но не стоит. Так же, там есть некоторое пояснение, как заставить ожить fx:id, но я все же хочу дополнить эту статью своими наблюдениями и знаниями в оригинальной статье.
Модель эта, кстати, не так очевидна, даже если смотреть статьи на Oracle. По крайней мере, я не нашел у Oracle, как мне работать с fx:id. Зато очень много экспериментировал, что и привело к пониманию, как с ними работать.
Итак, с предисловием пора заканчивать, к делу.
Что конкретно не очевидно из примеров в статьях? Примеры в интернетах, предлагают в FXML оформить дизайн приложения, после создать к нему класс-контроллер, который наследуется от Application, в нем определить метод start() (или сделать это в классе Main, разные есть примеры) и там пользоваться вашими fx:id. И это работает. Казалось бы, чудненько, все так просто, что даже хочется сплясать.
Вот даже банальный пример, естественно "hello world":
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.control.Button?>
<Pane xmlns="http://javafx.com/javafx/1.8.0.261" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Main">
<Button fx:id="fxButton" text="clickMe" onAction="#click"/>
</Pane>
public class Main extends Application {
@FXML
public Button fxButton;
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public void click(ActionEvent actionEvent) {
System.out.println("Hello World");
fxButton.setText("Hey!");
}
}
Это полностью рабочий пример. В данном примере, в FXML определяется Pane, в ней одна кнопка Button, у которой fx:id="fxButton", при нажатии на нее, вызывается метод в классе-контроллере onAction="#click". В методе click есть вывод на консоль и назначения текста самой кнопке.
Если его запустить и ткнуть в кнопку, то в консоли получим результат, у кнопки изменится ее название. Лихо? А вот и нет. Это не вносит ясности, как с этим работать. И такими примерами пестрит интернет. А если не делать MVC модель или каким-либо иным способом не разделять и властвовать, получится каша, на которой подскользнешься, ну и как говорят во всех американских фильмах, "упадешь и сломаешь бедро". Причем, бедренная кость — одна из самых крепких…
Следующим, логичным казалось бы шагом, было бы взять в этом же коде выше, убрать из него метод click и поработать напрямую, из кода. Например из метода start(), чтобы далеко не ходить, добавить в него обработку клика мышки на кнопку fxButton (панель/иную часть интерфейса, не имеет значения, это простой пример fx:id):
public class Main extends Application {
@FXML
public Button fxButton;
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
// добавляем слушателя, по клику мышки выполним действие (вывод в консоль):
fxButton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("Hello World"));
}
}
Вас обматерит ваша IDE еще при запуске
Exception
SPL
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
at sample.Main.start(Main.java:25)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
… 1 more
Exception running application sample.Main
Process finished with exit code 1
В первый миг, захочется материться в ответ, ведь не ясно, почему не инициализирована переменная. Ведь это контроллер, он знает про FXML файл, в него с успехом обращаются элементы интерфейса и обрабатываются, ведь в коде с методом click мы так и делали, обращались по fx:id.
Но это работает только в методах, в которые они жестко закодированы в FXML. А при прямом обращении из кода java в файл FXML, а не наоборот, получается, что объявленная в классе переменная Button fxButton, к которой мы в методе успешно обратились — не инициализирована. Вот казалось бы, незадача. И волки вроде сыты, да и овцы целы, но вот пастух слегка лукавит...
Ваша IDE, например, IDEA, вполне успешно генерирует пример выше, модель в нем верная(генерируются FXML и классы Controller, Main и немного кода в нем). Этого достаточно для начала работы. Я немного дописал кода, для наглядности, но сделал это в Main классе, вместо контроллера, для экономии места.
Итак, выходит что для взаимодействия с вашими node в в FXML файле, вам требуется создать метод, в котором действие будет обработано. Но обратите внимание, именно действие по элементу интерфейса. Внутри метода, можно так же использовать fx:id.
Но, стоит задуматься о использовании кнопки из примера выше в других частях кода (точнее выразиться, использовании fx:id этих элементов), даже в этом же классе (а это — контроллер), вас ждет NullPointerException и отсутствие понимания, собственно, WHY? А вдруг я хочу в коде ссылаться на какую-либо панель, сделав ей отдельный fx:id, менять текст или внешний вид форм, при этом не взаимодействуя физически с кнопками и прочими элементами, делая это из кода, согласно какой-то логике? Какое верное решение?
Это настолько не очевидно, учитывая отсутствие информации по данному вопросу, что я ушел в магазин за пивом...
Вернувшись и проковыряв дыру в интернете и в голове, перепробовав разные варианты, я докопался до истины. Местами в интернете, видел предложения провести инициализацию. Собственно, это и оказалось решением, но нигде опять же, нет примеров. По такому случаю, сейчас примеры с разъяснениями будут у меня. Как должна выглядеть программа на javaFX, прилагаю код.
FXML. Внешний вид. Необходимо определить в нем контроллер
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<Pane xmlns="http://javafx.com/javafx/1.8.261" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
<VBox layoutX="14.0" prefHeight="50.0" prefWidth="50.0">
<Button fx:id="fxButton" onAction="#click" text="clickMe" />
<Label fx:id="labelFx" minHeight="17.0" minWidth="185.0" text="label" />
</VBox>
</Pane>
Main. Единственная задача, запустить приложение, загрузить сцену из FXML
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller. Адаптер FXML и java кода.
public class Controller extends View implements Initializable {
@FXML
private Button fxButton;
@FXML
private Label labelFx;
@FXML
Label localLabel;
@FXML
public void click(ActionEvent actionEvent) {
System.out.println("Hello World");
fxButton.setText("Hey!");
labelLocalInitialize();
}
private void labelLocalInitialize(){
localLabel = labelFx;
localLabel.setText("local variable control");
}
@Override
public void initialize(URL location, ResourceBundle resources) {
//Assigning local variable viewLabel in class View to reference fx:id labelFx
setViewLabelText("transfer of control in View variable");
// add a listener, by mouse click, execute the action (output to the console):
fxButton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("Listener triggered"));
}
}
View. Отвечает за то, что отображает приложение.
public class View {
@FXML
private Label viewLabel;
public void setViewLabel(Label label){
viewLabel = label;
}
public void setViewLabelText(String text){
viewLabel.setText(text);
}
}
В контроллере и Viev я показал, как можно взаимодействовать разными способами с fx:id.
- Прямо закодировать в FXML вызов метода в контроллере.
- Инициализировать используемые id и иже с ними node и передавать в необходимое место в коде, вплоть до присваивания локальным переменным этих node по их fx:id.
Резюмируя:
- При инициализации через initialize(), достаточно просто обратиться к любой node по ее fx:id. Это инициализирует все node, которые определены в FXML. И они будут доступны и в Controller и во View
- onДействие из FXML, которое, например как в коде выше, вызывает метод click, так же инициализирует все, аналогично методу initialize
- Чтобы передать управление по fx:id классу, который не является контроллером или View, нужно создать локальную переменную в классе, где вам необходимо управление и присвоить ей значение в контроллере или View.
- Во View требуется проводить вручную инициализацию каждой переменной, присваивая ей значение не требуется, там достаточно просто создать переменную с именем fx:id, при инициализации в контроллере, она автоматически получит ссылку на node с оригинальным именем.
- Минимальная программа на JavaFX должна содержать FXML и классы Controller, Main. Если она не однокнопочная, само собой.
- Main.java — класс, отвечающий лишь за запуск приложения и загрузку вашего FXML. Никаких более действий, он не выполняет.
- Controller.java — класс, являющийся прослойкой между кодом на java и FXML файлом. Адаптер, если угодно. Через него происходит связь всех ссылок fx:id, в его методах обрабатываются вызовы интерактивных элементов интерфейса, тут же происходит инициализация.
Где-то выше я говорил, что есть магия в javaFX. Она начинается в классе View. Вроде, очевидно бы было, если бы от контроллера можно было наследовать классы, для работы с id, но происходит обратное… Почему так сделано, я в подробности не вдавался, если в комментариях люди знающие приоткроют завесу тайны, буду весьма благодарен.
===========
Источник:
habr.com
===========
Похожие новости:
- [Angular, Разработка под Java ME, Java, JavaScript, VueJS] Three-ific: Top 3 JavaScript Framework for 2021 and beyond
- [Разработка веб-сайтов, JavaScript, Математика] Математика верстальщику не нужна 2: Матрицы, базовые трансформации, построение 3D и фильтры для картинок
- [JavaScript, Дизайн, Конференции, Программирование] 25 и 26 сентября — открытые дни на Frontend Live
- [Программирование, Scala] Scala мертва?
- [JavaScript, Разработка веб-сайтов] Проверяем формы по стандартам с Validation API
- [JavaScript, ReactJS, Программирование] Почему это антипаттерн? (перевод)
- [Разработка веб-сайтов, JavaScript, VueJS] Вышел Vue.js 3.0 «One piece» (перевод)
- [JavaScript, Программирование, Разработка веб-сайтов] Server-Sent Events: пример использования
- [JavaScript, PostgreSQL, Программирование, Алгоритмы] Immutable Trie: найди то, не знаю что, но быстро, и не мусори
- Выпуск Vue.js 3.0.0, фреймворка для создания пользовательских интерфейсов
Теги для поиска: #_java, #_java, #_javafx, #_fxml, #_fx:id, #_java
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 00:23
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Мне кажется, не оправданно много полезных статей не только не посвящают и двух слов самому животрепещущему вопросу при начале работы с JavaFX, но и посвятив, все равно не раскрывают его полностью. А вопрос возникает следующий: как наладить связь ваших node по их fx:id и вашего кода. Как использовать их в разных частях кода, чтобы ссылаться на ваш программный интерфейс? Вот на это, я и постараюсь ответить под катом Что такое fx:id и с чем его едят По какой-то причине, для авторов статей и комментаторов на StackOverFlow не очевидно, что попросту не понятно для читателя, как происходит связь fx:id ссылок с вашим кодом. Потому что это не очевидно. А некоторые моменты, вообще больше похожи на магию, этот момент я отдельно упомяну ниже. Вообще, многие статьи полезны, информативны (особенно на английском), так же, есть ответы почти на все на StackOverFlow. Но, практически нигде развернуто не сказано, как именно работать с fx:id, которые мы определяем в FXML файле. Лишь краткие упоминания, которые приводят к еще большей путанице в голове. Обычно пишут "задайте вашей node нужный вам fx:id и будем вам счастье". К сожалению, счастья не будет. Будет NullPointerException. По причине некорректного использования, которое идет из непонимания области видимости, скажем так, этих id. И я хочу рассказать, по какой причине получается exception, а главное, как корректно связать ваш FXML с классом-контроллером и java-кодом. Надеюсь, это поможет людям избежать тех мучений, которые прошел я в поисках ответа на данный вопрос. Я бы наверно и пришел к ответу сам, рано или поздно, но спустя многие часы дни поиска, я наткнулся на статью. В ней рассказано про MVC модель, которую и следует использовать при разработке на JavaFX. Не стану повторять написанное в статье, там достаточное описание этой модели. Если вы о ней не слышали, то к прочтению обязательно, поскольку можно обойтись работая с javaFX вообще без FXML, на чистом java коде, но не стоит. Так же, там есть некоторое пояснение, как заставить ожить fx:id, но я все же хочу дополнить эту статью своими наблюдениями и знаниями в оригинальной статье. Модель эта, кстати, не так очевидна, даже если смотреть статьи на Oracle. По крайней мере, я не нашел у Oracle, как мне работать с fx:id. Зато очень много экспериментировал, что и привело к пониманию, как с ними работать. Итак, с предисловием пора заканчивать, к делу. Что конкретно не очевидно из примеров в статьях? Примеры в интернетах, предлагают в FXML оформить дизайн приложения, после создать к нему класс-контроллер, который наследуется от Application, в нем определить метод start() (или сделать это в классе Main, разные есть примеры) и там пользоваться вашими fx:id. И это работает. Казалось бы, чудненько, все так просто, что даже хочется сплясать. Вот даже банальный пример, естественно "hello world": <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?> <?import javafx.scene.control.Button?> <Pane xmlns="http://javafx.com/javafx/1.8.0.261" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Main"> <Button fx:id="fxButton" text="clickMe" onAction="#click"/> </Pane> public class Main extends Application {
@FXML public Button fxButton; @Override public void start(Stage primaryStage) throws Exception{ Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml")); primaryStage.setTitle("Hello World"); primaryStage.setScene(new Scene(root, 300, 275)); primaryStage.show(); } public static void main(String[] args) { launch(args); } public void click(ActionEvent actionEvent) { System.out.println("Hello World"); fxButton.setText("Hey!"); } } Это полностью рабочий пример. В данном примере, в FXML определяется Pane, в ней одна кнопка Button, у которой fx:id="fxButton", при нажатии на нее, вызывается метод в классе-контроллере onAction="#click". В методе click есть вывод на консоль и назначения текста самой кнопке. Если его запустить и ткнуть в кнопку, то в консоли получим результат, у кнопки изменится ее название. Лихо? А вот и нет. Это не вносит ясности, как с этим работать. И такими примерами пестрит интернет. А если не делать MVC модель или каким-либо иным способом не разделять и властвовать, получится каша, на которой подскользнешься, ну и как говорят во всех американских фильмах, "упадешь и сломаешь бедро". Причем, бедренная кость — одна из самых крепких… Следующим, логичным казалось бы шагом, было бы взять в этом же коде выше, убрать из него метод click и поработать напрямую, из кода. Например из метода start(), чтобы далеко не ходить, добавить в него обработку клика мышки на кнопку fxButton (панель/иную часть интерфейса, не имеет значения, это простой пример fx:id): public class Main extends Application {
@FXML public Button fxButton; @Override public void start(Stage primaryStage) throws Exception{ Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml")); primaryStage.setTitle("Hello World"); primaryStage.setScene(new Scene(root, 300, 275)); primaryStage.show(); // добавляем слушателя, по клику мышки выполним действие (вывод в консоль): fxButton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("Hello World")); } } Вас обматерит ваша IDE еще при запуске ExceptionSPLException in Application start method
java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389) at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767) Caused by: java.lang.RuntimeException: Exception in Application start method at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NullPointerException at sample.Main.start(Main.java:25) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863) at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326) at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294) at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177) … 1 more Exception running application sample.Main Process finished with exit code 1 В первый миг, захочется материться в ответ, ведь не ясно, почему не инициализирована переменная. Ведь это контроллер, он знает про FXML файл, в него с успехом обращаются элементы интерфейса и обрабатываются, ведь в коде с методом click мы так и делали, обращались по fx:id. Но это работает только в методах, в которые они жестко закодированы в FXML. А при прямом обращении из кода java в файл FXML, а не наоборот, получается, что объявленная в классе переменная Button fxButton, к которой мы в методе успешно обратились — не инициализирована. Вот казалось бы, незадача. И волки вроде сыты, да и овцы целы, но вот пастух слегка лукавит... Ваша IDE, например, IDEA, вполне успешно генерирует пример выше, модель в нем верная(генерируются FXML и классы Controller, Main и немного кода в нем). Этого достаточно для начала работы. Я немного дописал кода, для наглядности, но сделал это в Main классе, вместо контроллера, для экономии места. Итак, выходит что для взаимодействия с вашими node в в FXML файле, вам требуется создать метод, в котором действие будет обработано. Но обратите внимание, именно действие по элементу интерфейса. Внутри метода, можно так же использовать fx:id. Но, стоит задуматься о использовании кнопки из примера выше в других частях кода (точнее выразиться, использовании fx:id этих элементов), даже в этом же классе (а это — контроллер), вас ждет NullPointerException и отсутствие понимания, собственно, WHY? А вдруг я хочу в коде ссылаться на какую-либо панель, сделав ей отдельный fx:id, менять текст или внешний вид форм, при этом не взаимодействуя физически с кнопками и прочими элементами, делая это из кода, согласно какой-то логике? Какое верное решение? Это настолько не очевидно, учитывая отсутствие информации по данному вопросу, что я ушел в магазин за пивом... Вернувшись и проковыряв дыру в интернете и в голове, перепробовав разные варианты, я докопался до истины. Местами в интернете, видел предложения провести инициализацию. Собственно, это и оказалось решением, но нигде опять же, нет примеров. По такому случаю, сейчас примеры с разъяснениями будут у меня. Как должна выглядеть программа на javaFX, прилагаю код. FXML. Внешний вид. Необходимо определить в нем контроллер <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <Pane xmlns="http://javafx.com/javafx/1.8.261" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller"> <VBox layoutX="14.0" prefHeight="50.0" prefWidth="50.0"> <Button fx:id="fxButton" onAction="#click" text="clickMe" /> <Label fx:id="labelFx" minHeight="17.0" minWidth="185.0" text="label" /> </VBox> </Pane> Main. Единственная задача, запустить приложение, загрузить сцену из FXML public class Main extends Application {
@Override public void start(Stage primaryStage) throws Exception{ Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml")); primaryStage.setTitle("Hello World"); primaryStage.setScene(new Scene(root, 300, 275)); primaryStage.show(); } public static void main(String[] args) { launch(args); } } Controller. Адаптер FXML и java кода. public class Controller extends View implements Initializable {
@FXML private Button fxButton; @FXML private Label labelFx; @FXML Label localLabel; @FXML public void click(ActionEvent actionEvent) { System.out.println("Hello World"); fxButton.setText("Hey!"); labelLocalInitialize(); } private void labelLocalInitialize(){ localLabel = labelFx; localLabel.setText("local variable control"); } @Override public void initialize(URL location, ResourceBundle resources) { //Assigning local variable viewLabel in class View to reference fx:id labelFx setViewLabelText("transfer of control in View variable"); // add a listener, by mouse click, execute the action (output to the console): fxButton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("Listener triggered")); } } View. Отвечает за то, что отображает приложение. public class View {
@FXML private Label viewLabel; public void setViewLabel(Label label){ viewLabel = label; } public void setViewLabelText(String text){ viewLabel.setText(text); } } В контроллере и Viev я показал, как можно взаимодействовать разными способами с fx:id.
Резюмируя:
Где-то выше я говорил, что есть магия в javaFX. Она начинается в классе View. Вроде, очевидно бы было, если бы от контроллера можно было наследовать классы, для работы с id, но происходит обратное… Почему так сделано, я в подробности не вдавался, если в комментариях люди знающие приоткроют завесу тайны, буду весьма благодарен. =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 00:23
Часовой пояс: UTC + 5