JavaFX 8-Tabpanes и вкладки с отдельными FXML и контроллерами для каждой вкладки
Я надеюсь получить некоторые ответы относительно наличия fx: включить заявления для каждой вкладки в tabpane. Мне удалось легко получить контент, чтобы показать, но ссылки на методы связанного класса контроллера просто дают мне исключение nullpointerreference независимо от того, как я его структурирую. Контроллеры включенных макетов FXML не имеют ни конструктора, ни методов initialize (), необходимы ли они? Я пробовал разные вещи, но всегда получал одно и то же. исключение.
Я просто добавил прослушиватель изменений в tabpane, и когда была нажата вкладка, я хотел заполнить некоторые текстовые поля некоторыми значениями, полученными из глобально доступного arraylist. Примечание: arraylist не является проблемой, выполнение этой операции с помощью главного контроллера работает нормально.
Я собираюсь добавить пример кода в ближайшее время, но не могу прямо сейчас. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация, иначе я отправлю код позже сегодня.
*Edit, вот мой пример кода, взятый из другого потока здесь, в StackOverflow. JavaFX TabPane - один контроллер для каждой вкладки
файла testapp.java:
public class TestApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(new StackPane());
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/MainTestWindow.fxml"));
scene.setRoot(loader.load());
MainTestController controller = loader.getController();
controller.init();
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
главный контроллер, где я хочу ссылаться на суб контроллеры.
public class MainTestController {
@FXML private TabPane tabPane;
// Inject tab content.
@FXML private Tab fooTabPage;
// Inject controller
@FXML private FooTabController fooTabPageController;
// Inject tab content.
@FXML private Tab barTabPage;
// Inject controller
@FXML private BarTabController barTabPageController;
public void init() {
tabPane.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends Tab> observable,
Tab oldValue, Tab newValue) -> {
if (newValue == barTabPage) {
System.out.println("Bar Tab page");
barTabPageController.handleButton();
} else if (newValue == fooTabPage) {
System.out.println("Foo Tab page");
fooTabPageController.handleButton();
}
});
}
}
главный вид .FXML-файл
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.Tab?>
<TabPane fx:id="tabPane" fx:controller="controller.MainTestController" xmlns="http://javafx.com/javafx/8.0.40"
xmlns:fx="http://www.w3.org/2001/XInclude">
<tabs>
<Tab fx:id="fooTabPage" text="FooTab">
<fx:include source="fooTabPage.fxml"/>
</Tab>
<Tab fx:id="barTabPage" text="BarTab">
<fx:include source="barTabPage.fxml"/>
</Tab>
</tabs>
</TabPane>
FooTab:
public class FooTabController {
@FXML private Label lblText;
public void handleButton() {
lblText.setText("Byebye!");
}
}
FooTab по .FXML-файл:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://www.w3.org/2001/XInclude" fx:controller="controller.FooTabController">
<Label fx:id="lblText" text="Helllo"/>
<Button fx:id="btnFooTab" onAction="#handleButton" text="Change text"/>
</VBox>
BarTab:
public class BarTabController {
@FXML private Label lblText;
public void handleButton() {
lblText.setText("Byebye!");
}
}
BarTab по .FXML-файл
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://www.w3.org/2001/XInclude" fx:controller="controller.BarTabController">
<Label fx:id="lblText" text="Helllo" />
<Button fx:id="btnBarTab" onAction="#handleButton" text="Change text"/>
</VBox>
выше onaction для обоих FooTab и BarTab работает с соответствующих кнопок. Когда этот метод (handleButton) является ссылками от главного контроллера, тогда я получаю исключение.
2 ответов
чтобы ввести контроллер для включенного файла FMXL, вам нужно на <fx:include>
элемент. Контроллер будет введен в поле с "Controller"
добавляется fx:id
значение.
если вы хотите, чтобы ввести фактические Tab
тоже нужен отдельный fx:id
для этого.
так:
<tabs>
<Tab fx:id="fooTab" text="FooTab">
<fx:include fx:id="fooTabPage" source="fooTabPage.fxml"/>
</Tab>
<Tab fx:id="barTab" text="BarTab">
<fx:include fx:id="barTabPage" source="barTabPage.fxml"/>
</Tab>
</tabs>
и
@FXML private TabPane tabPane;
// Inject tab content.
@FXML private Tab fooTab;
// Inject controller
@FXML private FooTabController fooTabPageController;
// Inject tab content.
@FXML private Tab barTab;
// Inject controller
@FXML private BarTabController barTabPageController;
заключение: образец шаблона "inject SubControllers"
- вышеприведенный пример очень помог мне понять, наконец, механизм инъекции. Спасибо.
- Я переделал код, чтобы сделать его еще более прозрачным и понятным
- следующий код завершен и работает
Tab1fooController.Ява
public class TabPaneRootController {
@FXML private TabPane tabPane;
//###################################Inject part#############################################
// Inject tab content
@FXML private Tab tab1_foo; //from TabPaneRootView.fxml: <Tab fx:id="tab1_foo" ...>
@FXML private Tab tab2_bar; //from TabPaneRootView.fxml: <Tab fx:id="tab2_bar" ...>
// Inject tab controller
@FXML private Tab1fooController xxx_tab1foo_xxxController;//TabPaneRootView.fxml_include_fx:id="xxx_tab1foo_xxx" + "Controller"
@FXML private Tab2barController xxx_tab2bar_xxxController;//TabPaneRootView.fxml_include_fx:id="xxx_tab2bar_xxx" + "Controller"
//###########################################################################################
public void init() {
tabPane.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends Tab> observable,
Tab oldValue, Tab newValue) -> {
if (newValue == tab2_bar) {
System.out.println("- 2.Tab bar -");
System.out.println("xxx_tab2bar_xxxController=" + xxx_tab2bar_xxxController); //if =null => inject problem
xxx_tab2bar_xxxController.handleTab2ButtonBar();
} else if (newValue == tab1_foo) {
System.out.println("- 1.Tab foo -");
System.out.println("xxx_tab1foo_xxxController=" + xxx_tab1foo_xxxController); //if =null => inject problem
xxx_tab1foo_xxxController.handleTab1ButtonFoo();
} else {
System.out.println("- another Tab -");
}
});
}
}
tabPaneRootView.FXML-файл
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?
<?import javafx.scene.control.TabPane?>
<TabPane fx:id="tabPane" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.TabPaneRootController">
<tabs>
<Tab fx:id="tab1_foo" text="myTab1foo">
<fx:include fx:id="xxx_tab1foo_xxx" source="tab1fooView.fxml" />
</Tab>
<Tab fx:id="tab2_bar" text="myTab2bar">
<fx:include fx:id="xxx_tab2bar_xxx" source="tab2barView.fxml" />
</Tab>
</tabs>
Tab1fooController.java
public class Tab1fooController {
@FXML private Label tab1_label_showText;
public void handleTab1ButtonFoo() {
if( tab1_label_showText.getText().equals("tab1 aaa") ) {
tab1_label_showText.setText("tab1 iii");
} else {
tab1_label_showText.setText("tab1 aaa");
}
}
}
tab1fooView.FXML-файл
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.Tab1fooController">
<Label fx:id="tab1_label_showText" text="Tab1_start" />
<Button fx:id="tab1_button_foo" onAction="#handleTab1ButtonFoo" text="tab1_button_foo" />
</VBox>
Tab2barController.java
public class Tab2barController {
@FXML private Label tab2_label_showText;
public void handleTab2ButtonBar() {
if( tab2_label_showText.getText().equals("tab2 bbb") ) {
tab2_label_showText.setText("tab2 jjj");
} else {
tab2_label_showText.setText("tab2 bbb");
}
}
}
tab2barView.FXML-файл
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="controller.Tab2barController">
<Label fx:id="tab2_label_showText" text="Tab2_start" />
<Button fx:id="tab2_button_bar" onAction="#handleTab2ButtonBar" text="tab2_button_bar" />
</VBox>
файла testapp.java
public class TestApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(new StackPane());
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/tabPaneRootView.fxml"));
scene.setRoot(loader.load());
TabPaneRootController controller = loader.getController();
controller.init();
primaryStage.setScene(scene);
primaryStage.setTitle("Inject TabController");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}