2012-11-20 146 views
6

我對java和javafx很陌生,並且遇到了一個我無法解決的問題。 我需要動態地將新的自定義控件添加到javafx場景中。此外,我需要主控制和添加控件之間的交互。 我在網上發現了一些有用的信息,但無法將它們放在一起。動態添加JavaFX2控件

所以我建立解釋一個小例子:

主類:

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

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

及其控制器:

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

而且現在控制到dyn amically補充:

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

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

的用法是:A fxml2應加入fxml1的橫向盒。然後在fxml1中點擊一個按鈕後,fxml2的選項卡應該改變。 您可以看看該圖像http://s13.postimage.org/uyrmgylo7/two_controlls.png

所以我的問題是:

  • 我怎麼可以添加一個或多個fxml2控制器到fxml1的橫向盒的?
  • 如何從另一個控件訪問控件或在控件之間通信?有關詳細信息,請參閱Fxml2Controller中的SelectionChanged()方法。

謝謝你在前進, solarisx

回答

5

你似乎已經混合了不少概念在一起時是不同的。首先,階段可以理解爲屏幕上的一個窗口。它有一個包含實際SceneGraph的Scene對象。在你的例子中,你正在創建一個新的舞臺和一個新的場景,其中填充第二個fxml文件的內容。這意味着,如果工作,第二個窗口將彈出包含你的東西。我不認爲這是你想達到的。此外,當FXMLLoader讀取文件時,它會查找指定爲其控制器的類並通過反射構造它的一個實例。這意味着,當您在載入它的fxml文件的控制器的構造函數中調用load方法時,會導致無限循環。

要理解的最後一件事是,load()返回的對象是一個任意節點,可以像其他任何節點一樣放入應用程序的SceneGraph中。

因此,爲了使你的概念工作,你應該做以下幾點:

  1. 移動加載代碼這是目前在你的第二個控制器,你的第一個控制器的方法BUTTON_ACTION的構造。
  2. 丟棄button_action中的新階段新場景代碼,並將FXMLLoader返回的節點添加到HBox的子節點中。
  3. 對於第二個問題,如果實際創建FXMLLoader的實例而不是調用靜態方法,則可以獲取控制器實例,並在其中使用load()方法。在調用load()之後,您可以通過getController()getRoot()來檢索fxml文件的控制器和根對象。然後,您可以像使用邏輯中的任意對象一樣使用它們。
+0

感謝您的回答。隨着第1點和第2點。我現在可以將Fxml2添加到Fxml1中。但訪問控件仍然不清楚。將Fxml2添加到Fxml1中後,如果Fxml2中發生了某些情況,我想在Fxml1中更改某些內容。我在Fxml2Controller()代碼中添加了onSelectionChanged方法以獲得更好的解釋。我認爲問題是,我沒有得到Fxml1的當前實例。 – solarisx

+0

好的。在Sebastians 3. point和[訪問FXML控制器類]中找到了我的第二個問題的答案(http://stackoverflow.com/questions/10751271/accessing-fxml-controller-class?lq=1)。要在訪問控制器時避免出現null,請參見[如何訪問JavaFx 2.0中的Controller類?](http://stackoverflow.com/questions/10240471/how-can-i-access-a-controller-class-in- JavaFX的2-0) – solarisx