web-dev-qa-db-fra.com

Comment créer plusieurs contrôleurs javafx avec différents fichiers fxml?

J'ai regardé des blogs et d'autres questions de stackoverflow, et je ne vois pas de réponse directe à ma question. Je crée un client javafx gui et je veux que ma barre de menus soit un contrôleur dans un fxml, puis je veux que la zone de contenu soit des fichiers fxml supplémentaires. L'écran de connexion sera un fxml, après l'écran de connexion sera le contenu principal de l'application et qui sera dans un fxml. Comment dois-je procéder?

Je ne veux tout simplement pas avoir tout mon code pour ma connexion, la barre de menu et le contenu principal dans le même fichier. Voici une image de ce sur quoi je travaille:

enter image description here

22
j will

Utilisez FXML comme composants en utilisant une classe Java Java personnalisée comme fx: root et comme fx: contrôleur de votre fichier FXML: http://docs.Oracle.com/javafx/2 /fxml_get_started/custom_control.htm

Pour ce faire, vous devez appeler le constructeur de votre classe Java classe FXMLLoader personnalisée qui chargera votre FXML. L'avantage est de changer la façon dont FXML charge les composants.

La manière classique d'instancier des composants via FXMLLoader avec des contrôleurs imbriqués est: FXML d'abord, puis contrôleur pour chaque partie.

Avec cette technique, c'est: contrôleur d'abord, puis FXML pour chaque composant. Et vous ne chargerez pas directement FXML dans FXML, vous importerez vos classes Java Java personnalisées dans FXML).

Il s'agit d'une meilleure abstraction (pas besoin de savoir comment un composant est implémenté lorsque vous les importez dans FXML) et aide à réutiliser le code car c'est comme implémenter un widget personnalisé avec prise en charge FXML. Pour rendre votre composant réutilisable, assurez-vous que votre implémentation n'a pas de couplage étroit avec d'autres parties, ou utilisez IOC pour ce faire (par exemple, avec l'intégration de Spring avec JavaFX). De cette façon, vous pourra importer votre composant dans n'importe quelle partie de votre application (tout comme un widget DateInput) sans souci et vous ne dupliquerez pas de code.

Dans votre cas, vous aurez:

public class MenuBox extends VBox {

@FXML
private LoginBox loginBox;

@FXML
private ProfilesBox profilesBox;

public MenuBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class LoginBox extends VBox {
public LoginBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class ProfilesBox extends VBox {
public ProfilesBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

Et vous importerez LoginBox et ProfilesBox dans menu.fxml qui gère la mise en page globale de votre page:

<?import com.foo.bar.LoginBox ?>
<?import com.foo.bar.ProfilesBox ?>
<fx:root type="javafx.scene.layout.VBox"
    xmlns:fx="http://javafx.com/fxml">

<!-- Stuff here to declare the menu bar-->

    <HBox>
       <ProfilesBox fx:id="profilesBox"/>
       <LoginBox fx:id="loginBox"/>
    </HBox>

</fx:root>

login.fxml et profiles.fxml contiennent uniquement des composants de base.

28
zenbeni
  1. Vous pouvez inclure des documents FXML l'un dans l'autre - cela devrait vous aider à séparer la logique de conception

  2. Cela signifie que vous pouvez avoir contrôleurs imbriqués - un pour chaque document.

À partir de la documentation, vous pouvez maintenant configurer votre code de telle sorte que la logique puisse être séparée et invoquée à partir du contrôleur racine (si nécessaire).

J'espère que cela pourra aider.

5
Harsha R

J'avais besoin d'une fenêtre contextuelle avec des exigences similaires (plus de contrôle sur les nœuds et la disposition).

Après avoir parcouru les recommandations, j'ai trouvé une solution qui pourrait être utile.

Tout d'abord, j'ai créé un deuxième document fxml et un deuxième contrôleur (dans NetBeans, Nouveau -> FXML vide ... -> Utiliser Java -> Créer nouveau ...).

Un petit défi était de comprendre comment construire la scène dans le contrôleur principal et la connecter au contrôleur popup.

Le lien Passing Parameters JavaFX FXML donne de très bonnes idées et techniques.

Le code final ressemble à ceci (j'espère qu'il peut aider quelqu'un):

// Anchor Pane from the popup
@FXML
AnchorPane anchorPanePopup;

@FXML
private void soneButtonAction(ActionEvent event) throws IOException {     
    Stage newStage = new Stage();
    AnchorPane anchorPanePopup = (AnchorPane) FXMLLoader.load(getClass().getResource("Popup_FXML.fxml"));
    Scene scene = new Scene(anchorPanePopup);
    newStage.setScene(scene);
    newStage.initModality(Modality.APPLICATION_MODAL);
    newStage.setTitle("Dialog Window");
    newStage.showAndWait();        
}
1
rainer
package javafxapplication11;
import Java.io.IOException;
import Java.net.URL;
import Java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;

public class FXMLDocumentController implements Initializable {
@FXML
private CheckBox c1;

@FXML
private CheckBox c2;

public void clicked1(ActionEvent e) throws IOException {
Parent home_page_parent 
=FXMLLoader.load(getClass().getResource("AddDcuFXML.fxml"));
 Scene home_page_scene = new Scene(home_page_parent);
 Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
  app_stage.hide(); //optional
  app_stage.setScene(home_page_scene);
  app_stage.show();
   }
   public void clicked2(ActionEvent e) throws IOException {
   Parent home_page_parent 
    =FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
   Scene home_page_scene = new Scene(home_page_parent);
   Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
    app_stage.hide(); //optional
      app_stage.setScene(home_page_scene);
         app_stage.show();
     }
      public void clicked3(ActionEvent e) throws IOException {
     Parent home_page_parent 
   =FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
    Scene home_page_scene = new Scene(home_page_parent);
    Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
     app_stage.hide(); //optional
     app_stage.setScene(home_page_scene);
     app_stage.show();
      }
     @Override
       public void initialize(URL arg0, ResourceBundle arg1) {
        // TODO Auto-generated method stub
           } 
               }
0
Laxmi