2012-11-20 10 views
6

Jestem całkiem nowy dla java i javafx i mam problem, którego nie mogłem rozwiązać. Potrzebuję dynamicznie dodawać nowe niestandardowe formanty do sceny javafx. Ponadto potrzebuję interakcji między główną kontrolą a dodanymi kontrolami. Znalazłem już kilka przydatnych informacji w Internecie, ale nie udało się ich połączyć.Dodawanie formantów JavaFX2 dynamicznie

Więc zbudować mały przykład dla wyjaśnienia:

główne klasy:

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

Głównym 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> 

i jej kontroler:

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

I teraz kontrola do dyn amically dodać:

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

i kontroler:

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

Wykorzystanie jest: fxml2 należy dodać hbox z fxml1. Następnie, po kliknięciu przycisku w fxml1, zakładki fxml2 powinny się zmienić. Można spojrzeć na tym obrazie http://s13.postimage.org/uyrmgylo7/two_controlls.png

Więc moje pytania to:

  • w jaki sposób można dodać jeden lub więcej sterownika fxml2 do hbox z fxml1?
  • Jak mogę uzyskać dostęp do jednego kontrolera z innego lub komunikować się pomiędzy kontrolerami? Więcej szczegółów zawiera metoda onSelectionChanged() w sterowniku Fxml2Controller.

Dziękuję z góry, solarisx

Odpowiedz

5

Wydaje się, że miesza się sporo koncepcji ze sobą, które są odrębne. Przede wszystkim, Etap może być rozumiane jako okno na ekranie. Ma obiekt sceny, który przechowuje rzeczywisty SceneGraph. W twoim przykładzie tworzysz nowy etap i nową scenę, która zostanie wypełniona, która jest zawartością twojego drugiego pliku fxml. Oznacza to, że jeśli działa, pojawi się drugie okno zawierające twoje rzeczy. Nie sądzę, że to jest to, co chcesz osiągnąć.

Ponadto, gdy FXMLLoader odczytuje plik, szuka klasy, która jest określona jako kontroler i konstruuje jej instancję za pomocą odbicia. Oznacza to, że wywołując metodę load w konstruktorze kontrolera pliku fxml, który ładujesz, wywołujesz nieskończoną pętlę.

Ostatnią rzeczą, którą należy zrozumieć, jest to, że obiekt zwracany przez load() jest dowolnym węzłem, który można umieścić w aplikacji SceneGraph aplikacji, podobnie jak każdy inny węzeł.

Więc, aby swoją pracę pojęcie, należy dokonać następujących czynności:

  1. Move ładowanie kodu, który jest obecnie w konstruktorze drugiego kontrolera do metody button_Action swojego pierwszego kontrolera.
  2. Wyrzuć nowy kod sceny nowej sceny w button_action i weź węzeł zwrócony przez FXMLLoader i dodaj go do dzieci HBox.
  3. Aby uzyskać drugie pytanie, można uzyskać instancję kontrolera, jeśli faktycznie tworzy się instancję obiektu FXMLLoader, zamiast wywoływać metodę statyczną, i użyć w niej metody load(). Po wywołaniu load() można pobrać kontroler i obiekt główny pliku fxml za pośrednictwem getController() i getRoot(). Możesz użyć ich tak, jak dowolnego dowolnego obiektu w twojej logice.
+0

Dzięki za odpowiedź. Z punktem 1. i 2. mogę teraz dodać Fxml2 do Fxml1. Ale dostęp do kontroli wciąż nie jest dla mnie jasny. Po dodaniu Fxml2 do Fxml1 chcę coś zmienić w Fxml1, jeśli coś dzieje się w Fxml2. Dodałem metodę onSelectionChanged w kodzie Fxml2Controller() dla lepszego wyjaśnienia. Myślę, że problem polega na tym, że nie dostałem aktualnej instancji Fxml1. – solarisx

+0

Ok. Znaleziono odpowiedź na moje drugie pytanie w Sebastians 3. point i [Dostęp do klasy kontrolera FXML] (http://stackoverflow.com/questions/10751271/accessing-fxml-controller-class?lq=1). Aby uniknąć pustej wartości podczas uzyskiwania dostępu do kontrolera, zobacz [Jak uzyskać dostęp do klasy kontrolera w JavaFx 2.0?] (Http://stackoverflow.com/questions/10240471/how-can-i-access-a-controller-class-in- javafx-2-0) – solarisx

Powiązane problemy