2016-05-30 100 views
0

我在處理一些java fx組件時觀察到一些奇怪的行爲。我試圖通過控制器動態地將孩子添加到父節點,一旦在GUI上按下按鈕。這是問題的一個可重複的場景:父節點失去孩子

VBox vbox = new VBox(); 
    HBox entry = new HBox(); 
    Button button = new Button(); 
    TextField text = new TextField(); 

    entry.getChildren().add(text); 
    entry.getChildren().add(button); 

    vbox.getChildren().add(entry); 

    System.out.println(vbox.getChildren().isEmpty() ? "empty" : "not empty"); //prints out "not empty" 
    HBox newEntry = new HBox(entry); 
    System.out.println(vbox.getChildren().isEmpty() ? "empty" : "not empty"); //prints out "empty" 

能否請您賜教爲什麼vbox失去entry作爲一個孩子的時候我通過entry一個構造?我將entry傳遞給構造函數,以便複製已通過FXML表單設置的所有其他對象屬性/屬性。在我的實際代碼中,每個元素都有一個不同的標識符,通過node.setId()方法設置,因此重複ID不是問題。我沒有意識到一些潛在的機制?謝謝。

+0

你應該做'HBox中newEntry =條目;'而不是'新HBox中(輸入);' – ScriptKiddy

+0

我不這麼認爲,因爲然後'newEntry'仍然指向'entry',我在'newEntry'中修改的內容將修改'entry' – Marius

回答

3

我將entry傳遞給構造函數,以便複製已通過FXML表單設置的所有其他對象屬性/屬性。

它不這樣工作。該構造函數將新創建的HBox的子項添加爲相同的實例。由於Node只能有一個父親,並且發生在Parent的子列表中,因此JavaFX必須通過從其父母的子列表中刪除Node來修復狀態。

請注意,不少Pane s允許您將子項傳遞給其中一個構造函數。這些是而不是複製構造函數,但只是「快捷方式」,允許您添加孩子而不使用pane.getChildren().addAll(children);事實上,我不知道在JavaFX API中有Node的任何拷貝構造函數。

HBox newEntry = new HBox(entry); 

創建一個包含entry,因爲它是唯一的孩子一個新的HBox

不是試圖複製場景圖的一部分,而是創建一個輔助方法來創建場景圖的一部分(也可以使用fxml文件完成),這樣做通常更容易。

(有JavaFX的API中沒有功能,允許您創建一個Node層次的副本。)

+0

感謝您的回覆。即便如此,如果它是相同的實例,並且'entry'要從'vbox'中移除,那麼我會希望'newEntry'成爲'vbox'的子項?那你有什麼建議?當我按下GUI上的按鈕時,是否有解決方法而不創建新的FXML並加載它? – Marius

+0

@Marius它不是'newEntry',它和'entry'是同一個實例。你確實創建了一個新的'HBox',但是'HBox'獲得了小時候提到的實例。創建一個新的fxml將是最好的方法,因爲對於節點層次結構沒有「複製」功能,並且對於通常的'Node'類型,該功能的任何實現都需要大量使用反射來複制屬性值,甚至這在某些情況下會失敗(例如,如果沒有默認構造函數)並且比簡單創建新的fxml更復雜。 – fabian

+0

是的,我也這麼認爲。我必須最終通過反射..呃..然後我會只使用一些Java腳本,我猜。也試圖首先克隆「節點」,但沒有奏效。令人驚訝的是,雖然你可以有'新HBox(anotherHBox)'和'新VBox(另一個VBox)',但是你不能'new Button(anotherButton)'..無論如何。我確信有這樣的解釋:/您能否將您評論的文本添加到答案的正文中,以便我可以選擇答案作爲答案。謝謝你的麻煩。 – Marius