代码之家  ›  专栏  ›  技术社区  ›  Måns Thörnvik

JavaFX 8-选项卡窗格和选项卡,每个选项卡有单独的FXML和控制器

  •  19
  • Måns Thörnvik  · 技术社区  · 8 年前

    我希望得到一些关于在选项卡窗格中为每个选项卡使用fx:include语句的答案。我轻松地获得了显示内容的内容,但关联控制器类的引用方法只会给我一个nullpointerreference异常,无论我如何构造它。包含的FXML布局的控制器既没有构造函数也没有initialize()方法,是否需要它们?我尝试了一些不同的方法,但总是得到相同的例外。

    我所做的只是将更改侦听器添加到选项卡窗格中,当按下选项卡时,我想用从全局可访问的数组列表中获得的值填充一些文本字段。注意:阵列列表不是问题所在,使用主控制器执行此操作可以正常工作。

    我将很快添加一个代码示例,但现在无法添加。如果你需要更多信息,请告诉我,否则我会在今天晚些时候发布代码。

    *编辑,这是我的代码示例,取自StackOverflow上的另一个线程。 JavaFX TabPane - One controller for each tab

    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>
    

    食品标签:

    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>
    

    条形选项卡:

    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>
    

    上面针对FooTab和BarTab的onAction都适用于它们各自的按钮。当这个方法(handleButton)是来自主控制器的引用时,我就会得到一个异常。

    2 回复  |  直到 8 年前
        1
  •  18
  •   James_D    8 年前

    要为包含的FMXL文件注入控制器,您需要一个 fx:id 属性 <fx:include> 要素控制器将被注入具有 "Controller" 附加到 传真:id 价值

    如果你想注入 Tab 传真: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;
    
        2
  •  2
  •   Sten    8 年前

    结论:样本模板“注入子控制器”
    -上面的例子最终帮助我理解了注入机制。非常感谢。
    -我重新编写了代码,使其更加透明和清晰
    -下面的代码是完整的并且可以工作

    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 -");
                }
            });
        }
    }
    

    选项卡窗格工具栏视图.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>
    

    选项卡1fooController.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");
            }
        }
    }
    

    选项卡1fooView.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>
    

    选项卡2bar控制器.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");
            }
        }
    }
    

    tab2bar视图.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>
    

    测试应用.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);
        }
    }
    

    - Directory structure
    - Example started