web-dev-qa-db-ja.com

JavaFX TabPane-各タブに1つのコントローラー

Fxは初めてです。 10個のタブがあるTabPanelがあります。各タブには多くのコントロール(チャート、ボタンなど)があり、各タブにコントローラーを割り当てたいのです。 SceneBuilderでは、ビュー全体にコントローラーを割り当てることしかできません。つまり、トップパネル(ルート)のみに「コントローラークラス」オプションがあるため、1つのクラスのすべてのタブのコードを記述する必要があります。必然的に、非常に大規模なクラスになり、理解と保守が困難になります。おそらく解決策は非常に簡単ですが、私が言うように、私はFXの経験がほとんどなく、ウェブ上で同様のものを見つけることができませんでした。

何か案が?ありがとうございました。

27
roneypc

1つの方法は、各タブページを、独自の関連付けられたコントローラークラスを持つ個別のFXMLファイルにカプセル化することです。

次に、メインタブコントロールのFXMLファイルで、次のようなことができます。

<TabPane fx:controller="com.foo.MainController">
    <tabs>
        <Tab text="Untitled Tab 1">
            <content>
                <fx:include fx:id="fooTabPage" source="fooTabPage.fxml"/>
            </content>
        </Tab>
        <Tab text="Untitled Tab 2">
            <content>
                <fx:include fx:id="barTabPage" source="barTabPage.fxml"/>
            </content>
        </Tab>
    </tabs>
</TabPane>

コンテンツを直接埋め込む代わりに、fx:includeディレクティブは、FXMLLoaderに、参照されているFXMLファイルをロードするよう指示します。ページコンテンツに使用される個々のFXMLファイルにはすべて独自のコントローラーがあり、ロジックがうまく分離されます。

メインコントローラーからサブページまたはサブコントローラーとやり取りする必要がある場合は、他のFXMLコントロールと同様にそれらを参照して、それらを挿入できます。

public class MainController {
    // Inject tab content.
    @FXML private FooTabPage fooTabPage;
    // Inject controller
    @FXML private FooTabController fooTabPageController;

    // Inject tab content.
    @FXML private BarTabPage barTabPage;
    // Inject controller
    @FXML private BarTabController barTabPageController;
}

多数のページ(それぞれに独自のコントロールが多数ある)がある場合は、各タブを空のままにして、メインビューが読み込まれたら、関連するページをコントロールに読み込みます。

コンテンツを切り替えるにはタブの変更をリッスンし、関連するコードを追加して、タブページのコンテンツに使用されているビューをロード/アンロードする必要があります。

パフォーマンスの問題を発見した場合は、最初のアプローチから始めて、リファクタリングして2番目のアプローチを使用することをお勧めします。

74
Benjamin Gale