2017-06-09 2 views
0

mein Layout ist: MVEJavaFX Interaktion in stackpane mit mehreren Controllern

ich Schwierigkeiten haben, mit den Controllern anderer Klassen interagieren (ja, ich weiß, es gibt mehrere Threads darüber - aber ich bekomme immer noch nicht, was falsch).

Also, im Grunde habe ich eine StackPane "root", die zwei AnchorPane enthält: "vertMenu" und "Inhalt". "root" Das StackPane ist in einer VBox für Layout-Zwecke verschachtelt. "vertMenu" enthält verschiedene Schaltflächen zum Laden von Inhalten (von fxml-Dateien) in den Inhaltsbereich - nicht implementiert in diesem MVE.

Ich möchte "menuButton" in der Klasse RootController drücken, um "vertMenu" von der VertMenuController-Klasse zu deaktivieren, um mit der Benutzeroberfläche im Inhaltsbereich zu interagieren, der von der ContentController-Klasse stammt.

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

Root-Controller-Klasse:

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(); 

    } 


} 

Stammansicht:

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

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 Klasse

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


} 

InhaltAlle

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

Ich bekomme keine Ausnahmen, so dass ich denke, ich richtig einen Verweis auf die "verticalMenuController" in der machen Root-Controller-Klasse. Leider kann ich das AnchorPane "vertMenu" nicht deaktivieren.

Vielen Dank bis jetzt.

Antwort

0

Wenn Sie mit

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

vertMenuC.disableMenu(); 

die FXMLLoader erstellt eine neue Instanz der Benutzeroberfläche definiert in VertMenuView.fxml und eine neue Controller-Instanz die FXML-Datei laden, die zu diesem UI zugeordnet ist. Sie weisen der lokalen Variablen root das Stammverzeichnis der Benutzeroberfläche zu. Wenn Sie vertMenuC.disableMenu aufrufen, deaktivieren Sie das Menü in der neuen Instanz der Benutzeroberfläche, die von FXMLLoader erstellt wurde. Diese Benutzeroberfläche ist jedoch eine andere Instanz als die, die von der <fx:include> geladen und angezeigt wurde, sodass Sie keinen Effekt sehen.

Stattdessen benötigen Sie einen Verweis auf den Controller, der der Benutzeroberfläche zugeordnet ist, die vom Element <fx:include> geladen wird. Sie können dies durch injecting the "Nested Controller" in den Hauptcontroller tun.

Fügen Sie zunächst ein fx:id zu Ihrem fx:include:

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

Und dann injizieren diese in Ihre RootController. Die Regel ist, dass der Feldname für den Regler ist die fx:id mit dem Text "Controller" angefügt:

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

    @FXML private void initialize() { 

    } 

    // ... 

} 

Jetzt können Sie nur disableMenu auf dem injizierten Controller direkt anrufen:

@FXML private void menuButtonAction() { 

    vertMenuController.disableMenu(); 

} 

Sie müssen wahrscheinlich tun das gleiche mit Ihrem ContentController auch.

+0

Aah macht Sinn. Ich hatte nicht im Sinn, dass dies natürlich eine neue Instanz der Benutzeroberfläche erstellen würde ... Danke! – Michael

Verwandte Themen