2012-11-20 5 views
6

Je suis assez nouveau pour java et javafx et j'ai un problème que je n'ai pas pu résoudre. Je dois ajouter dynamiquement de nouveaux contrôles personnalisés à une scène javafx. En outre, j'ai besoin d'interaction entre le contrôle principal et les contrôles ajoutés. J'ai déjà trouvé quelques informations utiles sur le web mais je n'ai pas pu les rassembler.Ajout dynamique de contrôles JavaFX2

Alors je construis un petit exemple pour l'explication:

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

La principale FXML:

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

et son contrôleur:

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

Et maintenant le contrôle de dyn amically ajouter:

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

et le controleur:

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'utilisation est: Un fxml2 doit être ajouté à la hbox de fxml1. Ensuite, après un clic sur un bouton dans fxml1, les onglets de fxml2 devraient changer. Vous pouvez jeter un oeil à cette image http://s13.postimage.org/uyrmgylo7/two_controlls.png

Mes questions sont les suivantes:

  • comment puis-je ajouter un ou plusieurs du contrôleur fxml2 dans le hbox de fxml1?
  • Comment puis-je accéder à un contrôle d'un autre ou communiquer entre les contrôleurs? Voir la méthode onSelectionChanged() dans Fxml2Controller pour plus de détails.

Nous vous remercions à l'avance, solarisx

Répondre

5

Vous semblez avoir mélangé assez peu concepts ensemble qui sont distincts. Tout d'abord, une étape peut être comprise comme une fenêtre sur l'écran. Il a un objet Scene qui contient le SceneGraph réel. Dans votre exemple, vous créez une nouvelle scène et une nouvelle scène remplie avec le contenu de votre second fichier fxml. Cela signifie que, si vous travaillez, une deuxième fenêtre apparaîtra contenant vos affaires. Je ne pense pas que ce soit ce que vous voulez réaliser. En outre, lorsque le FXMLLoader lit un fichier, il recherche la classe spécifiée comme contrôleur et en construit une instance via la réflexion. Cela signifie que lorsque vous appelez la méthode load dans le constructeur du contrôleur du fichier fxml que vous chargez avec, vous créez une boucle infinie. La dernière chose à comprendre est que l'objet load() renvoyé est un nœud arbitraire qui peut être placé dans le SceneGraph de votre application comme n'importe quel autre nœud.

Donc, pour faire fonctionner votre concept, vous devez faire ce qui suit:

  1. Déplacer le chargement de code qui est actuellement dans le constructeur de votre deuxième contrôleur à la méthode button_Action de votre premier contrôleur.
  2. Jetez le code de nouvelle scène dans la commande button_action et récupérez le nœud renvoyé par le FXMLLoader et ajoutez-le aux enfants du HBox.
  3. Pour votre deuxième question, vous pouvez obtenir l'instance du contrôleur si vous créez réellement une instance d'un FXMLLoader au lieu d'appeler la méthode statique, et utilisez la méthode load(). Après avoir appelé load(), vous pouvez récupérer le contrôleur et l'objet racine du fichier fxml via getController() et getRoot(). Vous pouvez ensuite les utiliser comme n'importe quel objet arbitraire dans votre logique.
+0

Merci pour votre réponse. Avec le point 1. et 2. je peux ajouter Fxml2 maintenant dans Fxml1. Mais l'accès aux contrôles n'est toujours pas clair pour moi. Après avoir ajouté un Fxml2 dans Fxml1, je veux changer quelque chose dans Fxml1 si quelque chose se passe dans Fxml2. J'ai ajouté une méthode onSelectionChanged dans le code Fxml2Controller() pour une meilleure explication. Je pense que le problème est, que je n'ai pas obtenu l'instance actuelle du Fxml1. – solarisx

+0

Ok. Trouvé la réponse à ma deuxième question dans Sebastians 3. point et [Accès à la classe contrôleur FXML] (http://stackoverflow.com/questions/10751271/accessing-fxml-controller-class?lq=1). Pour éviter les valeurs nulles lors de l'accès au contrôleur, voir [Comment puis-je accéder à une classe de contrôleur dans JavaFx 2.0?] (Http://stackoverflow.com/questions/10240471/how-can-i-access-a-controller-class-in- javafx-2-0) – solarisx

Questions connexes