2012-11-20 21 views
6

Tôi khá mới đối với java và javafx và có một vấn đề mà tôi không thể giải quyết được. Tôi cần phải tự động thêm điều khiển tùy chỉnh mới vào cảnh javafx. Hơn nữa tôi cần sự tương tác giữa điều khiển chính và các điều khiển bổ sung. Tôi đã tìm thấy một số thông tin hữu ích trên web nhưng không thể kết hợp với nhau.Thêm các điều khiển JavaFX2 động

Vì vậy, tôi xây dựng một ví dụ nhỏ cho lời giải thích:

lớp học chính:

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

Các fxml chính:

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

và bộ điều khiển của nó:

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

Và bây giờ điều khiển để dyn amically thêm:

fxml của nó:

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

và khiển:

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

Việc sử dụng là: Một fxml2 nên được bổ sung vào hbox của fxml1. Sau đó, sau khi nhấp vào nút trong fxml1, các tab của fxml2 sẽ thay đổi. Bạn có thể có một cái nhìn vào hình ảnh mà http://s13.postimage.org/uyrmgylo7/two_controlls.png

Vì vậy, câu hỏi của tôi là:

  • làm thế nào tôi có thể thêm một hoặc nhiều bộ điều khiển fxml2 vào hbox của fxml1?
  • làm cách nào tôi có thể truy cập một điều khiển từ một điều khiển khác hoặc liên lạc giữa các bộ điều khiển? Xem phương thức onSelectionChanged() trong Fxml2Controller để biết chi tiết.

Cảm ơn bạn trước, solarisx

Trả lời

5

Bạn dường như đã trộn lẫn khá một vài khái niệm với nhau mà là khác biệt. Trước hết, Giai đoạn có thể được hiểu là cửa sổ trên màn hình. Nó có một đối tượng Scene chứa SceneGraph thực tế. Trong ví dụ của bạn, bạn đang tạo một Stage mới và một Scene mới được điền đầy nội dung của tệp fxml thứ hai của bạn. Điều này có nghĩa rằng, nếu làm việc, một cửa sổ thứ hai sẽ bật lên có chứa nội dung của bạn. Tôi không nghĩ rằng đây là những gì bạn muốn đạt được.

Hơn nữa, khi FXMLLoader đọc một tệp, nó sẽ tìm lớp được chỉ định làm bộ điều khiển và xây dựng một thể hiện của nó thông qua sự phản chiếu. Điều này có nghĩa rằng khi bạn gọi phương thức tải trong hàm khởi tạo của bộ điều khiển của tệp fxml mà bạn đang tải với nó, bạn đang gây ra một vòng lặp vô hạn.

Điều cuối cùng cần hiểu là đối tượng trả về load() là một nút tùy ý có thể được đưa vào SceneGraph của ứng dụng giống như bất kỳ nút nào khác.

Vì vậy, để làm cho công việc ý tưởng của mình, bạn nên thực hiện như sau:

  1. Move tải mã mà hiện đang trong constructor của bộ điều khiển thứ hai của mình với phương BUTTON_ACTION của bộ điều khiển đầu tiên của bạn.
  2. Vứt bỏ mã cảnh mới-giai đoạn mới trong button_action và lấy nút được trả về bởi FXMLLoader và thêm nó vào con của HBox.
  3. Đối với câu hỏi thứ hai, bạn có thể lấy trường hợp bộ điều khiển nếu bạn thực sự tạo một thể hiện của FXMLLoader thay vì gọi phương thức tĩnh và sử dụng phương thức load() trong đó. Sau khi gọi load() bạn có thể truy xuất bộ điều khiển và đối tượng gốc của tệp fxml qua getController()getRoot(). Sau đó bạn có thể sử dụng chúng giống như bất kỳ đối tượng tùy ý nào trong logic của bạn.
+0

Cảm ơn câu trả lời của bạn. Với điểm 1. và 2. tôi có thể thêm Fxml2 vào Fxml1. Nhưng việc truy cập các điều khiển vẫn chưa rõ ràng với tôi. Sau khi thêm một Fxml2 vào Fxml1 tôi muốn thay đổi một cái gì đó trong Fxml1 nếu một cái gì đó xảy ra trong Fxml2. Tôi đã thêm một phương thức onSelectionChanged trong mã Fxml2Controller() để có giải thích tốt hơn. Tôi nghĩ rằng vấn đề là, rằng tôi đã không nhận được trường hợp hiện tại của Fxml1. – solarisx

+0

Ok. Tìm thấy câu trả lời cho câu hỏi thứ hai của tôi ở tại Sebastians 3. điểm và [Truy cập lớp điều khiển FXML] (http://stackoverflow.com/questions/10751271/accessing-fxml-controller-class?lq=1). Để tránh null khi truy cập vào bộ điều khiển, hãy xem [Làm thế nào tôi có thể truy cập một lớp Bộ điều khiển trong JavaFx 2.0?] (Http://stackoverflow.com/questions/10240471/how-can-i-access-a-controller-class-in- javafx-2-0) – solarisx

Các vấn đề liên quan