web-dev-qa-db-fra.com

JavaFX TabPane - Un contrôleur pour chaque onglet

Je suis nouveau sur Fx. J'ai un TabPanel avec 10 onglets. Chaque onglet possède de nombreux contrôles (graphiques, boutons, etc.), et ce que je veux, c'est assigner un contrôleur pour chaque onglet. Le SceneBuilder ne me permet d'affecter qu'un contrôleur pour la vue entière, je veux dire, seul le panneau supérieur (la racine) a l'option "Classe de contrôleur", donc je dois écrire le code pour tous les onglets dans une classe et ce, comme entraîner, résultant en une très grande classe et difficile à comprendre et à maintenir. Peut-être que la solution est très simple, mais comme je l'ai dit, j'ai très peu d'expérience avec FX et je n'ai pas pu trouver quelque chose de similaire sur le web.

Une idée? Je vous remercie.

27
roneypc

Une approche consiste à encapsuler chacune de vos pages à onglets dans un fichier FXML distinct avec sa propre classe de contrôleur associée.

Ensuite, dans votre fichier FXML pour le contrôle de l'onglet principal, vous pouvez faire quelque chose comme ceci:

<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>

Notez qu'au lieu d'incorporer le contenu directement, j'utilise le fx:include directive qui indique à FXMLLoader de charger le fichier FXML qui est référencé. Les fichiers FXML individuels utilisés pour le contenu de la page auront tous leur propre contrôleur afin que la logique soit bien séparée.

Si vous devez interagir avec les sous-pages ou les sous-contrôleurs du contrôleur principal, vous pouvez les référencer comme vous le faites avec tout autre contrôle FXML pour les injecter.

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

Si vous avez un grand nombre de pages (chacune avec un grand nombre de ses propres contrôles), une autre approche consiste à laisser chaque onglet vide, et une fois la vue principale chargée, chargez la page appropriée dans votre contrôle.

Vous devez écouter les modifications apportées aux onglets pour changer le contenu et ajouter le code approprié pour charger/décharger les vues utilisées pour le contenu des pages à onglet.

Je recommanderais de commencer par la première approche et de refactoriser pour utiliser la deuxième approche si vous découvrez des problèmes de performances.

74
Benjamin Gale