2016-11-16 2 views
0

Brauchen Sie Hilfe? Dies mag eher eine Designperspektive sein, aber ich benutze dieses Muster überall in meiner Anwendung, wollte also eine Idee bekommen.JavaFX. Greifen Sie auf die Daten eines Controllers von einem anderen Controller zu

Beispiel Screenshot beigefügt. http://imgur.com/a/fuD5D

Meine Frage: Ich habe eine BorderPane die Art von Stammcontainer in meinem Fall ist (RootBorderPane.fmxl, RootBorderPaneController.java). Die Ansicht wurde mithilfe des Szenenerstellers erstellt. Ich werde die linke Seite als Navigationsleiste verwenden und basierend auf der Auswahl auf der linken Seite, werde ich eine neue Ansicht in den zentralen Bereich der RootBorderPane laden. Ich habe andere Ansichten wie diese (View1.fxml, View2.fxml, View3.fxml etc) (entworfen mit Szene-Builder) und entsprechende Controller (View1Controller.java, View2Controller.java, View3Controller.java usw.). View1, View2, View3 enthält TableViews für sich. Jetzt habe ich einige Tasten (Button1, Button2, Button3 etc) in der RootBorderPane der linken Seite und wenn ich Button1 und dann ich meine View1 (View1.fxml) laden und setzen Sie es im RootBorderPane Center-Bereich.

Ich klickte auf "Button1", auf der Schaltfläche klick ich lud die View1 und legte es auf das Zentrum des RootBorderPane. Diese Logik befindet sich im RootBorderPaneController.java View1 enthält ein TableView und die Daten für die Tabellenansicht werden geladen und auf der initialisierbaren() Methode des View1-Controllers (View1Controller.java) gesetzt. Ich bin in der Lage, alle oben genannten zu erreichen.

Problem: Ich habe Hinzufügen und Löschen im Navigationsbereich und diese Tasten sollten aktiviert/deaktiviert werden basierend auf dem Datensatz in der View1 der Tabellenansicht ausgewählt. (Die Schaltfläche Löschen sollte aktiviert sein, wenn in der Tabellenansicht ein Datensatz ausgewählt wurde, andernfalls sollte die Schaltfläche Hinzufügen nicht aktiviert sein)

Direkt oder indirekt ist meine Frage der Zugriff auf einen Controller von einem anderen Controller. Gibt es einen eleganten Design-Ansatz, um dies zu tun, anstatt die Referenz von einem Controller in dem anderen Controller zu behalten.

Vielen Dank im Voraus

+0

Siehe http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx –

Antwort

0

eine Möglichkeit zu lassen Sie die Steuerung Ihrer subPanes (VIEW_1 ... View_n) zugreifen, um sie zu laden, wie Sie es für Ihren Wurzelbereich tun.

// Load root layout from fxml file. 
FXMLLoader loader = new FXMLLoader(); 
rootLayout = loader.load(getClass().getResource("BorderPane.fxml").openStream()); 

BorderPaneController bpc = (BorderPaneController) loader.getController(); 

List<Pane> subPaneList = new ArrayList<>(); 
for (int i = 0; i < 30; i++) { 
    loader = new FXMLLoader(); 
    loader.setLocation(MainApp.class.getResource("View" + i + ".fxml")); 
    subPaneList.add((Pane) loader.load()); 
} 
bpc.setSubPaneList(subPaneList); 

// Show the scene containing the root layout. 
Scene scene = new Scene(rootLayout); 
primaryStage.setScene(scene); 
primaryStage.show(); 

jetzt brauchen Sie nur ein setSubPaneList (..) Methode in der bpc-Controller, und Sie werden die öffentlichen Methoden (zB Getter/Setter) Ihrer subPanes

+0

Sie keine Schleife haben sollte, nur die Knopfnummer, um die richtige Ansicht zu laden. – pdem

0

Es scheint, zugreifen können, dass Sie laden dynamisch die Ansicht mit FXML Loader, so sind hier die Regel es für die Anwendung:

  1. nicht statische Methode FXMLLoader verwenden sie, intanciate die FXMLLoader, um weitere Optionen auf sie (dh die Steuerung & Knoteninstanz)
  2. Ruft die Instanz des untergeordneten Controllers ab, die vom FXMLLoader vom Hauptcontroller bereitgestellt wird.
  3. Wählen Sie eine allgemeine Möglichkeit, zwischen Eltern-Kind-Controller zu betreiben: Ich schlage eine selectedProperty() -Methode vor.
  4. diese Eigenschaft von einer Schnittstelle Get so ist es für alle untergeordneten Steuerungen

I Property verwenden zu arbeiten zwischen Controllern in Ihrem Fall die selectedProperty von Tableview sollte die ideale Lösung zugänglich ist: Sie ausgewählt haben können Instanz , und Sie haben das Ereignis der Auswahl/Abwahl, die auf zwei Arten verwendet werden kann: einfach binden, oder fügen Sie einen Listener der Änderung in TableView getan.
Für diesen Fall ist die Bindung ausreichend.

Es gibt viele Dateien in dieser Lösung, so ist hier der Haupttrick: Vom Hauptcontroller, haben Sie die Instanz der selectedProperty des aktuellen Kindes, und binden Sie es an die visibleProperty Ihrer Schaltfläche, um es anzuzeigen.

buttonOpen.disableProperty().bind(controller.selectedProperty().isNull()); 

Sie, dass selectedProperty müssen wieder in den Code der Taste zum Öffnen

public void open(){ 
//TODO open in a view 
System.out.println("open the object"+selectedProperty().get() 
} 

Voll Quellen:

Java-Dateien

/** 
* App launch 
*/ 
public class SOFx extends Application{ 

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

    @Override 
    public void start(Stage primaryStage) throws Exception { 
    primaryStage.setTitle ("SO test"); 
    //static loading for index, don't need the controller. 
    Parent root = FXMLLoader.load(getClass().getResource("Index.fxml"),null); 
    Scene scene = new Scene(root); 
    primaryStage.setMaximized(true); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
    } 
} 

/** 
* Main Controller 
*/ 
public class IndexController { 


    @FXML 
    private BorderPane root; 

    @FXML 
    private Button buttonOpen; 

    private ObjectProperty<Object> selectedProperty; 

    public FXMLLoader loadFXML(URL url, ResourceBundle resources){ 
    FXMLLoader fxmlLoader = new FXMLLoader(); 
    fxmlLoader.setLocation (url); 
    fxmlLoader.setResources(resources); 
    try { 
     fxmlLoader.load(); 
     return fxmlLoader; 
    } catch (IOException e) { 
     e.printStackTrace(System.err); 
     throw new IllegalStateException(e); 
    } 
    } 

    public void button1(){ 
    FXMLLoader loadFXML = loadFXML(getClass().getResource("View1.fxml"),null); 
    root.setCenter(loadFXML.getRoot()); 
    ICenterController controller = (ICenterController) loadFXML.getController(); 
    selectedProperty = controller.selectedProperty(); 
    buttonOpen.disableProperty().bind(selectedProperty.isNull()); 
    } 

    public void open(){ 
    //TODO open in a view 
    System.out.println("open the object"+selectedProperty.get()); 
    } 

} 

/** 
* Interface of Center controllers 
*/ 
public interface ICenterController { 
ObjectProperty<Object> selectedProperty(); 
} 



/** 
* Child controller 
*/ 
public class View1Controller implements ICenterController { 

    private static final ObjectProperty<Object> selectedProperty = new SimpleObjectProperty(); 

    @Override 
    public ObjectProperty<Object> selectedProperty() { 
    return selectedProperty; 
    } 

    /** 
    * simulate TableView selection/deselection 
    */ 
    public void select(){ 
    selectedProperty.set(new Object()); 
    } 

    public void deselect(){ 
    selectedProperty.set(null); 
    } 

} 

Fxml Dateien, I don‘ t eine vollständige TableView, ich simuliere es mit den Tasten

Index.fxml

<BorderPane xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" 
     fx:controller="pdem.stackoverflow.IndexController" fx:id="root"> 

     <left> 
      <VBox> 
       <Button onAction="#button1" text="view1"/> 
       <Button fx:id="buttonOpen" text="open"/> 
      </VBox> 

     </left> 


    </BorderPane> 

View1.fxml

<VBox xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="pdem.stackoverflow.View1Controller" > 
      <Button onAction="#select" text="select"/> 
      <Button onAction="#deselect" text="deselect"/> 
</VBox> 
Verwandte Themen