2016-10-27 13 views
0

Referenz Artikel Applying MVC With JavaFxJavaFX eine Tableview von einem anderen FXML

Ich habe Schnittstelle 1 FXML folgenden

<SplitPane> 
    <items> 
     <TableView prefHeight="200.0" prefWidth="200.0"> 
      <columns> 
       <TableColumn prefWidth="75.0" text="User" /> 
       <TableColumn prefWidth="75.0" text="Pass" /> 
      </columns> 
     </TableView> 
     <fx:include source="Container.fxml"/> 
    </items> 
</SplitPane> 

Container.fxml es nur zum Speichern von XML-Schnittstelle Beispiel verwendet wird, ich verwenden, um InputData.fxml einbetten , Test.fxml auf TabPanel

Und Schnittstelle 3 InputData.xml Ich enthält TextField den Benutzernamen und das Passwort und eine Schaltfläche zum Speichern.

Ich mag jedes Mal, wenn ich die Taste, um das kann Schnittstelle 1 Tabelle aus dem Wert der Schnittstelle erhält Wert und Update 3

Da die Schnittstelle 3 Eingang data.xml nicht direkt in die eingebetteten speichern drücken, um fragen, 1-Schnittstelle nur angezeigt, wenn eligible.So ich kann keine Daten übertragen fxml direkt an folgende

 DataModel model = new DataModel(); 
     listController.initModel(model); 
     editorController.initModel(model); 
     menuController.initModel(model); 

es ist auf der Schnittstelle, wenn kann mir helfen bitte

+1

Verwenden Sie einen MVC-Ansatz zu erstellen: ein Modell zwischen den beiden Controllern teilen und die Daten aus dem Modell zugänglich machen. Siehe http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx –

+0

Danke für Ihre ausführliche Anleitung und vollständigen Quellcode –

+0

James_D Ein wenig gierig, aber ich habe noch eine Frage zum Thema erweiterte Datenupdates update a tableview von einem anderen FXML. Ich freue mich auf Ihre Hilfe: D –

Antwort

2

Zwei Ansätze hier.

Passing das Modell zu nested Controller

Sie können die Controller aus dem enthaltenen FXML in die Steuerung für die darunter FXML injizieren, um die nested controllers Technik. Dann kann der "äußere Controller" das Modell auf den "verschachtelten Controller" propagieren.

Also z.B. wenn Sie

<SplitPane xmlns="..." fx:controller="com.mycompany.MainController"> 
    <items> 
     <TableView prefHeight="200.0" prefWidth="200.0"> 
      <columns> 
       <TableColumn prefWidth="75.0" text="User" /> 
       <TableColumn prefWidth="75.0" text="Pass" /> 
      </columns> 
     </TableView> 
     <fx:include fx:id="container" source="Container.fxml"/> 
    </items> 
</SplitPane> 

Angenommen, der Controller-Klasse für Container.fxmlContainerController ist. Dann würden Sie tun:

public class MainController { 

    private Model model ; 

    @FXML 
    private ContainerController containerController ; // name is fx:id with "Controller" appended 

    public void setModel(Model model) { 
     this.model = model ; 
     containerController.setModel(model); 
     // ... 
    } 

    // ... 
} 

und natürlich

public class ContainerController { 

    private Model model ; 

    public void setModel(Model model) { 
     this.model = model ; 
     // ... 
    } 

    // ... 
} 

einen Controller Factory Mit

Wenn Sie eine Menge enthalten FXML Dateien und Controller haben, etc, kann diese beginnen wartbaren zu bekommen . In diesem Fall könnte es besser sein, das Modell in den Konstruktoren der Controller zu initialisieren und controllerFactory auf FXMLLoader zu verwenden, um Controller mit einem Modell zu erstellen, das an den Konstruktor übergeben wird. So, jetzt Sie Controller wie folgt aussehen:

public class MainController { 

    private final Model model ; 

    public MainController(Model model) { 
     this.model = model ; 
    } 

    public void initialize() { 
     // bind controls to model here... 
    } 
} 

und in ähnlicher Weise für ContainerController usw. Hinweis: Dies ist viel sauberer als die vorherigen Versionen, wo man über das Modell zu einer beliebigen Zeit eingestellt Sorge musste zu werden. Hier ist garantiert, dass es gesetzt wird, wenn Code im Controller ausgeführt wird.

Jetzt müssen Sie ein wenig Magie für die FMXLLoader die Controller korrekt erstellen, wenn die FXML geladen wird:

Model model = new Model(); 
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
Callback<Class<?>, Object> controllerFactory = (Class<?> type) -> { 
    try { 
     for (Constructor<?> c : type.getConstructors()) { 
      if (c.getParameterCount() == 1 && c.getParameterTypes()[0].equals(Model.class)) { 
       return c.newInstance(model); 
      } 
     } 
     // couldn't find constructor taking a model, just use default: 
     return type.newInstance(); 
    } catch (Exception exc) { 
     exc.printStackTrace(); 
     return null ; 
    } 
}; 
loader.setControllerFactory(controllerFactory); 

Parent root = loader.load(); 
// ... 

Beachten Sie, dass FXML Dateien über ein <fx:include>-Tag geladen wird die gleiche Steuerung Fabrik wie die Verwendung " einschließlich "FXML-Datei. So wird das gleiche Modell automatisch an den verschachtelten Controller übergeben.

DI Mit Frameworks

Schließlich, wenn Sie wirklich viel dies tun, könnten Sie eine Abhängigkeit inject Rahmen zu prüfen, indem Sie die Abhängigkeiten auf dem Modell zu verwalten. Afterburner.fx ist ein dedizierter JavaFX DI Rahmen, und dann ist alles so einfach wie

public class MainController { 

    @Inject 
    private Model model ; 

    public void initialize() { 
     // bind UI elements to model... 
    } 
} 

Sie auch Frühling oder Guice verwenden können. Z.B. Konfigurieren Sie die Controller mit Spring als Prototyp-Beans, das Modell als Singleton-Bean, und schreiben Sie die Controller so, dass sie das Modell wie mit "afterburner.fx" injizieren. Dann können Sie ein FXMLLoader sagen Frühling zu verwenden, um die Controller mit

// Spring application context: 
ApplicationContext appContext = ... ; 
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
loader.setControllerFactory(appContext::getBean); 
Parent root = loader.load(); 
+0

Methode 1: So übergeben Sie Werte zwischen Schnittstelle 1 Main.fxml und Schnittstelle 3 InputData.fxml.Ich muss gemeinsame Werte übertragen Modell für Container.fxml Zum Beispiel, wenn Ich habe viele container xml interface: container.fxml enthält container2.fxml enthält InputData. Ich brauche Modelle übertragen von Main.fxml = modell-> container.fxml = modell-> container2.fxml = modell-> InputData.fxml Methode 2: Ich verstehe nicht –

+1

@ MATAM Ich bin nicht sicher, ich verstehe die Frage wirklich in deinem letzten Kommentar: du hast genau beschrieben, wie es funktionieren soll. Jeder Controller, der einen Verweis auf das Modell benötigt, hat eine Methode 'setModel'. Wenn es einen verschachtelten Controller hat, der ebenfalls Zugriff auf das Modell benötigt, ruft seine Methode 'setModel' die Methode' setModel' des geschachtelten Controllers auf. Sie können das so tief verschachteln, wie Sie es brauchen, aber wie gesagt, es kann kompliziert werden, und an dieser Stelle könnte eine Controller-Fabrik einfacher sein. –

+0

Hallo James_D Vielen Dank für Ihre detaillierten Anweisungen, ich habe Methode 1 verstanden, wird es ein Problem, wenn zu viele verschachtelte Schnittstelle.Ihre Methode 2 ist sehr praktisch, aber ich weiß nicht, wie zu leisten.Ich kann Themen über Methode 2, drängen erstellen Sie helfen weiterhin http://stackoverflow.com/questions/40329861/javafx-using-a-controller-through-factory-to-update-other-xml-interface –

Verwandte Themen