web-dev-qa-db-ja.com

JavaFX 8-タブペインと、タブごとに個別のFXMLおよびコントローラーを備えたタブ

タブペインの各タブにfx:includeステートメントがあることについていくつかの回答を得たいと思います。関連するコントローラークラスの参照メソッドを表示するためのコンテンツを簡単に取得できましたが、どのように構造化しても、nullpointerreference例外が発生します。含まれているFXMLレイアウトのコントローラーには、コンストラクターやinitialize()メソッドもありません。それらは必要ですか?いくつかのことを試しましたが、常に同じ例外が発生しました。

私が単に行ったのは、タブペインに変更リスナーを追加することであり、タブが押されたときに、グローバルにアクセス可能な配列リストから取得したいくつかの値をテキストフィールドに入力したかったのです。注:arraylistは問題ではありません。メインコントローラーを使用してこの操作を実行しても問題ありません。

コード例をまもなく追加しますが、今はできません。詳細が必要な場合はお知らせください。それ以外の場合は、本日中にコードを投稿します。

*編集、ここに私のコード例を示します。ここではStackOverflowの別のスレッドから取得しています。 JavaFX TabPane-タブごとに1つのコントローラー

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>

上記のFooTabとBarTabのonActionは、それぞれのボタンで機能します。このメソッド(handleButton)がメインコントローラーからの参照である場合、例外が発生します。

15
Måns Thörnvik

含まれているFMXLファイルのコントローラーを挿入するには、fx:id要素に<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;
8
James_D

結論:サンプルテンプレート「サブコントローラーの挿入」
-上記の例は、ついに注入メカニズムを理解するのに非常に役立ちました。ありがとうございました。
-コードを作り直して、コードをさらに透明で明確にしました
-次のコードは完全で機能しています

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

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

-ディレクトリ構造
-例を開始しました

1
Sten