2017-06-09 3 views
0

ma mise en page est: MVEinteraction JavaFX dans stackpane avec plusieurs contrôleurs

J'ai du mal à interagir avec les contrôleurs d'autres classes (oui, je sais qu'il ya plusieurs discussions à ce sujet - mais je ne comprends toujours pas ce faux). Donc, fondamentalement, j'ai un StackPane "root" qui inclut deux AnchorPane: "vertMenu" et "content". "root" Le StackPane est imbriqué dans une VBox à des fins de mise en page. "vertMenu" contiendra différents boutons pour charger le contenu (à partir des fichiers fxml) dans le volet de contenu - non implémenté dans ce MVE. Je veux appuyer sur "menuButton" dans la classe RootController pour désactiver "vertMenu" de VertMenuController Class pour initeract avec l'interface utilisateur sur le volet de contenu qui provient de la classe ContentController.

Mon code:

package application; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.stage.Stage; 

import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.layout.BorderPane; 


public class Main extends Application { 
    private Stage stage; 
    @Override 
    public void start(Stage primaryStage) { 
     try { 
      this.stage = primaryStage; 
      FXMLLoader loader = new FXMLLoader(getClass().getResource("Root.fxml")); 
      Parent myPane = loader.load(); 

      Scene scene = new Scene(myPane); 
      primaryStage.setScene(scene); 

      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Classe racine Contrôleur:

package application; 

import java.io.IOException; 

import javafx.animation.KeyFrame; 
import javafx.animation.KeyValue; 
import javafx.animation.Timeline; 
import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.control.Button; 
import javafx.scene.layout.AnchorPane; 
import javafx.scene.layout.StackPane; 
import javafx.scene.layout.VBox; 
import javafx.util.Duration; 

public class RootController { 
    @FXML private StackPane root; 
    @FXML private Button menuButton; 
    @FXML private Button bb; 
    VertMenuController vertMenuC; 
    ContentController contentC; 

    @FXML private void initialize() { 

    } 

    @FXML private void menuButtonAction() throws IOException { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("VertMenuView.fxml")); 
     Parent root = loader.load(); 
     vertMenuC = loader.getController(); 

     vertMenuC.disableMenu(); 

    } 


} 

Racine Voir:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.AnchorPane?> 


<VBox prefHeight="450.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.RootController"> 
    <children> 
     <StackPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: rgb(222,222,222);"> 
     <children> 
      <fx:include source="ContentView.fxml" /> 
      <fx:include source="VertMenuView.fxml" /> 
     </children> 
     </StackPane> 
     <Button fx:id="menuButton" mnemonicParsing="false" onAction="#menuButtonAction" prefHeight="48.0" prefWidth="157.0" text="Button" /> 
     <Button fx:id="bb" mnemonicParsing="false" prefHeight="25.0" prefWidth="154.0" text="Button" /> 
    </children> 
</VBox> 

VertMenuController Classe

package application; 

import javafx.fxml.FXML; 
import javafx.scene.control.Button; 
import javafx.scene.layout.AnchorPane; 
import javafx.scene.layout.VBox; 

public class VertMenuController { 
    @FXML private AnchorPane vertMenu; 
    @FXML private Button b1; 
    @FXML private Button b2; 
    @FXML private VBox vbo; 


    public void disableMenu() { 
     vertMenu.setDisable(true); 
    } 
    public void enableMenu() { 
     vertMenu.setDisable(false); 
    } 

    public AnchorPane getVertMenu() { 
     return vertMenu; 
    } 
    public VBox getBox() { 
     return vbo; 
    } 


} 

VertMenuView

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.AnchorPane?> 

<AnchorPane fx:id="vertMenu" prefHeight="400.0" prefWidth="150.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.VertMenuController"> 
    <children> 
     <VBox fx:id="vbo" prefHeight="400.0" prefWidth="150.0"> 
     <children> 
      <Button fx:id="b1" mnemonicParsing="false" prefHeight="59.0" prefWidth="148.0" text="B1" /> 
      <Button fx:id="b2" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" prefHeight="59.0" prefWidth="148.0" text="B2" /> 
     </children> 
     </VBox> 
    </children> 
</AnchorPane> 

ContentController Classe

package application; 

import javafx.fxml.FXML; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.layout.AnchorPane; 

public class ContentController { 
    @FXML private AnchorPane content; 
    @FXML private Button b3; 
    @FXML private Label ausgabe; 



    @FXML private void b3Action() { 
     ausgabe.setText("b2 pressed"); 
    } 

    public void setAusgabe() { 
     this.ausgabe.setText("Hello World"); 
    } 


} 

ContentView

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.AnchorPane?> 

<AnchorPane fx:id="content" maxWidth="600.0" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ContentController"> 
    <children> 
     <VBox prefHeight="262.0" prefWidth="600.0"> 
     <children> 
      <Button fx:id="b3" mnemonicParsing="false" onAction="#b3Action" prefHeight="59.0" prefWidth="600.0" text="Button" /> 
      <Label fx:id="ausgabe" prefHeight="113.0" prefWidth="610.0" text="Label" /> 
     </children> 
     </VBox> 
    </children> 
</AnchorPane> 

Je ne reçois aucune exception, donc je pense que je fais correctement une référence à la "verticalMenuController" dans la classe de contrôleur racine. Mais malheureusement, je ne peux pas désactiver l'AnchorPane "vertMenu".

Merci beaucoup pour l'instant.

Répondre

0

Lorsque vous chargez le fichier FXML avec

FXMLLoader loader = new FXMLLoader(getClass().getResource("VertMenuView.fxml")); 
Parent root = loader.load(); 
vertMenuC = loader.getController(); 

vertMenuC.disableMenu(); 

le FXMLLoader crée une nouvelle instance de l'interface utilisateur définie dans VertMenuView.fxml et une nouvelle instance de contrôleur qui est associé à cette interface. Vous affectez la racine de l'interface utilisateur à la variable locale root. Lorsque vous appelez vertMenuC.disableMenu, vous désactivez le menu dans la nouvelle instance de l'interface utilisateur créée par le FXMLLoader. Toutefois, cette interface utilisateur est une instance différente de celle qui a été chargée et affichée par le <fx:include>, de sorte que vous ne voyez aucun effet. Au lieu de cela, vous avez besoin d'une référence au contrôleur associé à l'interface utilisateur qui est chargée par l'élément <fx:include>. Vous pouvez le faire par injecting the "Nested Controller" dans le contrôleur principal.

D'abord, ajouter un fx:id à votre fx:include:

<fx:include fx:id="vertMenu" source="VertMenuView.fxml" /> 

Et puis injecter dans votre RootController. La règle est que le nom du champ pour le contrôleur est le fx:id avec le texte "Controller" annexe:

public class RootController { 
    @FXML private StackPane root; 
    @FXML private Button menuButton; 
    @FXML private Button bb; 
    @FXML private VertMenuController vertMenuController; 

    @FXML private void initialize() { 

    } 

    // ... 

} 

Maintenant, vous pouvez simplement appeler disableMenu directement sur le contrôleur injecté:

@FXML private void menuButtonAction() { 

    vertMenuController.disableMenu(); 

} 

Vous avez probablement besoin de faire la même chose avec votre ContentController aussi.

+0

Aah a du sens. Je n'avais pas en tête que cela va bien sûr créer une nouvelle instance de l'interface utilisateur ... Merci! – Michael