java JavaFX 8 - 每个选项卡具有单独的 FXML 和控制器的选项卡和选项卡
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39164050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaFX 8 - Tabpanes and tabs with separate FXML and controllers for each tab
提问by M?ns Th?rnvik
I hope to get some answers regarding having fx:include statements for each tab in a tabpane. I have managed with ease to get content to show up BUT referencing methods of the associated controller class simply gives me a nullpointerreference exception no matter how I structure it. The controllers of the included FXML layouts do not have neither constructor not initialize() methods, are they needed? I tried some different things but always got the same exception.
我希望得到一些关于在 tabpane 中为每个选项卡设置 fx:include 语句的答案。我已经轻松地让内容显示出来,但是无论我如何构造它,关联控制器类的引用方法只会给我一个空指针引用异常。包含的 FXML 布局的控制器既没有构造函数也没有 initialize() 方法,是否需要它们?我尝试了一些不同的东西,但总是得到相同的例外。
What I simply did was add a change listener to the tabpane and when a tab was pressed I wanted to populate some textfields with some values gotten from a globally accessible arraylist. Note: the arraylist is not the issue, performing this operation using the main controller works fine.
我所做的只是向选项卡窗格添加一个更改侦听器,当按下选项卡时,我想用从全局可访问的数组列表中获取的一些值填充一些文本字段。注意:arraylist 不是问题,使用主控制器执行此操作可以正常工作。
I'm going to add a code example shortly but cannot right now. Please let me know if you need more info, otherwise I'll post the code later today.
我将很快添加一个代码示例,但现在不能。如果您需要更多信息,请告诉我,否则我将在今天晚些时候发布代码。
*Edit, here is my code example, taken from another thread here on StackOverflow. JavaFX TabPane - One controller for each tab
*编辑,这是我的代码示例,取自 StackOverflow 上的另一个线程。 JavaFX TabPane - 每个选项卡一个控制器
TestApp.java:
测试应用程序.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);
}
}
Main controller, where I want to reference the sub controllers.
主控制器,我想在其中引用子控制器。
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();
}
});
}
}
Main view's .fxml
主视图的 .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's .fxml:
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's .fxml
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>
The above onAction for both FooTab and BarTab works with their respective buttons. When this method (handleButton) is references from the Main controller, that's when I get an exception.
上面 FooTab 和 BarTab 的 onAction 与它们各自的按钮一起使用。当此方法 (handleButton) 是来自主控制器的引用时,我就会收到异常。
采纳答案by James_D
To inject a controller for an included FMXL file, you need an fx:id
attribute on the <fx:include>
element. The controller will be injected to a field with "Controller"
appended to the fx:id
value.
要为包含的 FMXL 文件注入控制器,您需要元素fx:id
上的属性<fx:include>
。控制器将被注入到"Controller"
附加到fx:id
值的字段中。
If you want to inject the actual Tab
too, you need a separate fx:id
for that.
如果你也想注入实际的Tab
,你需要一个单独fx:id
的。
So:
所以:
<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>
and
和
@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;
回答by Sten
Conclusion: Sample Template "inject SubControllers"
- the above example helped me very much to understand the inject mechanism at last. Thank you.
- I've reworked the code to make it even more transparent and clear
- the following code is complete and working
结论:示例模板“注入子控制器”
- 上面的示例最终帮助我非常了解注入机制。谢谢你。
- 我重新编写了代码,使其更加透明和清晰
- 以下代码完整且有效
Tab1fooController.java
Tab1fooController.java
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
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
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
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
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
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);
}
}