2012-11-20 19 views
6

Sono abbastanza nuovo per java e javafx e ho un problema che non ho potuto risolvere. Ho bisogno di aggiungere dinamicamente nuovi controller personalizzati a una scena javafx. Inoltre ho bisogno di interazione tra il controllo principale e i controlli aggiunti. Ho trovato già alcune informazioni utili nel web ma non riesco a metterlo insieme.Aggiunta dinamica di controlli JavaFX2

Così ho costruire un piccolo esempio per la spiegazione:

classe principale:

public class Test_TwoController extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 
     Parent root = FXMLLoader.load(getClass().getResource("Fxml1.fxml")); 
     Scene scene = new Scene(root);     
     stage.setScene(scene); 
     stage.show(); 
    }  
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Il fxml principale:

<AnchorPane id="fxml1_anchorpane_id" fx:id="fxml1_anchorpane" prefHeight="206.0" prefWidth="406.0" xmlns:fx="http://javafx.com/fxml" fx:controller="test_twocontroller.Fxml1Controller"> 
    <children> 
    <HBox id="fxml1_hbox_id" fx:id="fxml1_hbox" prefHeight="200.0" prefWidth="400.0"> 
     <children> 
     <Button id="fxml1_button_id" fx:id="fxml1_button" mnemonicParsing="false" onAction="#button_action" prefHeight="200.0" prefWidth="200.0" text="Button" /> 
     </children> 
    </HBox> 
    </children> 
</AnchorPane> 

e il suo controller:

public class Fxml1Controller implements Initializable { 

    @FXML HBox hbox; 
    @FXML Button button; 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { } 

    public void button_action(ActionEvent event) throws IOException { 
     // 1. add an instance of Fxml2 to hbox 
     // 2. change to tab2 in new Fxml2 
     // or 
     // notify Fxml2Controller to change to tab2 in Fxml2 
    } 
} 

E ora il controllo di dyn amically aggiungere:

sua fxml:

<AnchorPane id="fxml2_anchorpane_id" fx:id="fxml2_anchorpane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="200.0" xmlns:fx="http://javafx.com/fxml" fx:controller="test_twocontroller.Fxml2Controller"> 
    <children> 
    <TabPane id="fxml2_tabpane_id" fx:id="fxml2_tabpane" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE"> 
     <tabs> 
     <Tab id="fxml2_tab1_id" fx:id="fxml2_tab1" text="tab1"> 
      <content> 
      <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" /> 
      </content> 
     </Tab> 
     <Tab id="fxml2_tab2_id" fx:id="fxml2_tab2" onSelectionChanged="#onSelectionChanged" text="tab2"> 
      <content> 
      <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" /> 
      </content> 
     </Tab> 
     </tabs> 
    </TabPane> 
    </children> 
</AnchorPane> 

e il controler:

public class Fxml2Controller { 

    @FXML TabPane tabpane; 
    @FXML Tab tab1; 
    @FXML Tab tab2; 

    public Fxml2Controller() throws IOException { 
     Parent root = FXMLLoader.load(getClass().getResource("Fxml2.fxml")); 
     Scene scene = new Scene(root);   
     Stage stage = new Stage(); 
     stage.setScene(scene);   
    }  

    public void onSelectionChanged(Event e) throws IOException { 

     FXMLLoader loader = new FXMLLoader(); 
     // how can i get the current Fxml1 anchorpane instance? 
     AnchorPane root = (AnchorPane) loader.load(getClass().getResource("Fxml1.fxml").openStream()); 

     Button b = (Button)root.lookup("#fxml1_button_id");   
     b.setText("New Button Text"); // dont change the buttons text!!!    
} 
} 

L'utilizzo è: Un fxml2 deve essere aggiunto al hbox di fxml1. Quindi, dopo un clic del pulsante in fxml1, le schede di fxml2 dovrebbero cambiare. Si può avere uno sguardo a quella immagine http://s13.postimage.org/uyrmgylo7/two_controlls.png

Quindi le mie domande sono:

  • come posso aggiungere uno o più controller fxml2 nella hbox di fxml1?
  • come posso accedere a un controllo da un altro o comunicare tra i controller? Vedi il metodo onSelectionChanged() in Fxml2Controller per i dettagli.

Grazie in anticipo, solarisx

risposta

5

Lei sembra aver mescolato alcuni concetti bel insieme, che sono distinti. Prima di tutto, uno Stage può essere interpretato come una finestra sullo schermo. Ha un oggetto Scene che contiene l'attuale SceneGraph. Nel tuo esempio, stai creando un nuovo Stage e una nuova Scena che vengono riempiti con il contenuto del tuo secondo file fxml. Ciò significa che, se funzionante, apparirà una seconda finestra contenente i tuoi contenuti. Non penso che questo sia ciò che vuoi ottenere.

Inoltre, quando FXMLLoader legge un file, cerca la classe che è specificata come suo controller e ne costruisce un'istanza tramite riflessione. Ciò significa che quando si chiama il metodo load nel costruttore del controller del file fxml che si sta caricando con esso, si causa un loop infinito.

L'ultima cosa da capire è che l'oggetto che load() restituisce è un nodo arbitrario che può essere inserito nel SceneGraph dell'applicazione proprio come qualsiasi altro nodo.

Quindi, per rendere il vostro concetto di lavoro, si dovrebbe fare il seguente:

  1. Spostare il carico-codice che si trova attualmente nel costruttore del secondo controller al metodo button_Action del primo controller.
  2. Getta via il codice della nuova scena-scena in button_action e prendi il Nodo restituito da FXMLLoader e aggiungilo ai figli dell'HBox.
  3. Per la seconda domanda, è possibile ottenere l'istanza del controller se si crea effettivamente un'istanza di un FXMLLoader anziché chiamare il metodo statico e utilizzare il metodo load() al suo interno. Dopo aver chiamato load() è possibile recuperare il controller e l'oggetto radice del file fxml tramite getController() e getRoot(). Puoi quindi usarli come qualsiasi oggetto arbitrario nella tua logica.
+0

Grazie per la risposta. Con il punto 1. e 2. Posso aggiungere ora Fxml2 in Fxml1. Ma l'accesso ai controlli non è ancora chiaro per me. Dopo aver aggiunto un Fxml2 in Fxml1 voglio cambiare qualcosa in Fxml1 se succede qualcosa in Fxml2. Ho aggiunto un metodo onSelectionChanged nel codice Fxml2Controller() per una spiegazione migliore. Penso che il problema sia che non ho avuto l'istanza attuale di Fxml1. – solarisx

+0

Ok. Ho trovato la risposta alla mia seconda domanda in Sebastians 3. point e [Accedere alla classe controller FXML] (http://stackoverflow.com/questions/10751271/accessing-fxml-controller-class?lq=1). Per evitare null durante l'accesso al controller, vedere [Come posso accedere a una classe Controller in JavaFx 2.0?] (Http://stackoverflow.com/questions/10240471/how-can-i-access-a-controller-class-in- JavaFX-2-0) – solarisx

Problemi correlati