2016-08-24 22 views
1
@Override 
public void start(Stage primaryStage) { 
    this.primaryStage = primaryStage; 
    this.primaryStage.setTitle("AddressApp"); 

    initRootLayout(); 

    showTabOverview(); 
} 

/** 
* Initializes the root layout. 
*/ 
public void initRootLayout() { 
    try { 
     // Load root layout from fxml file. 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Main.class.getResource("rootLayout.fxml")); 
     rootLayout = (BorderPane) loader.load(); 

     // Show the scene containing the root layout. 
     Scene scene = new Scene(rootLayout); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

/** 
* Shows the Tab overview inside the root layout. 
*/ 
public void showTabOverview() { 
    try { 
     // Load person overview. 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Main.class.getResource("tabLayout.fxml")); 
     TabPane TabOverview = (TabPane) loader.load(); 

     // Set person overview into the center of root layout. 
     rootLayout.setCenter(TabOverview); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

它確實與我的tabpane的FXML一起工作。爲什麼當我使用scenebuilder創建一個選項卡時,它說不是一個節點?

<TabPane xmlns:fx="http://www.w3.org/1999/XSL/Transform"> 
<tabs> 
    <Tab text="Untitled Tab 1"> 
    </Tab> 
    <Tab text="Untitled Tab 2"> 
    </Tab> 
</tabs> 
</TabPane> 

但我想每個標籤FXML添加用這種方法我在this link

<Tab text="Untitled Tab 1"> 
     <content> 
      <fx:include fx:id="fooTabPage" source="fooTabPage.fxml"/> 
     </content> 
    </Tab> 

發現當我添加了包括與選項卡的新源它給了我IllegalArgumentException: Unable to coerce [email protected] to class javafx.scene.Node.

如何讓這些選項卡實際上成爲節點?有沒有具體的方法來創建它們?

+1

Kiper嗨,請在您的問題文本適當的資本,你可能獲得更多的upvotes和答案。我已經解決了這個問題。最好的祝福。 – Lii

+0

謝謝你,對不起! – Kiper

+1

似乎'fooTabPage.fxml'包含一個'Tab'作爲根節點。這應該是「Tab」的內容。當然你也可以使用'Tab'作爲'fooTabPage.fxml'的根元素,但是你需要刪除周圍的''部分,這樣fxml變得更難重用。 – fabian

回答

3

A Tab不是Node的子類,正如您從JavaDocs中看到的那樣。原因是JavaFX的作者想要將製表符放在中只有 in TabPane s:如果TabNode的子類,那麼你可以做,例如,HBox anyContainer = new HBox(new Tab(...));,這不會真的有意義(我懷疑JavaFX的的作者不想防守編碼Tab來處理這些情況。所以TabObjectTabPane一個子類中使用(很多很多有ObservableList<Tab>,您可以用getTabs()訪問。

FXMLLoader作品of)反射。這允許它在飛行中創建對象,其類由fxml文件確定,當然編譯器ne ver看到。因此,FXMLLoader沒有編譯時檢查由FXML文件創建的對象的類型。因此,您爲FXMLLoader的靈活性付出的代價是類型安全性的損失;這取決於您作爲程序員,以確保在FXML文件中爲其預期用途定義了正確的類型。

所以,如果你有FXML代碼如下:

<Tab text="Untitled Tab 1"> 
    <content> 
     <fx:include fx:id="fooTabPage" source="fooTabPage.fxml"/> 
    </content> 
</Tab> 

此,鬆散,轉化爲

Tab tab = new Tab("Untitled Tab 1"); 
tab.setContent(FXMLLoader.load(getClass().getResource("fooTabPage.fxml"))); 

由於setContent預計一Node,這樣只會成功,如果的fooTabPage.fxml根元素指的是Node

相反,如果的fooTabPage.fxml根元素是一個Tab,那麼你需要的<fx:include>在一個Tab將預期的地方發生。所以,你可以有fooTabPage.fxml

<?xml version="1.0" encoding="UTF-8"?> 
<!-- imports .... --> 
<Tab fx:controller="..." xmlns:fx="http://javafx.com/fxml/1"> 
    <content> 
     <!-- define content here... --> 
    </content> 
</Tab> 

,然後做

<TabPane> 
    <tabs> 
     <fx:include source="fooTabPane.fxml" /> 
    </tabs> 
</TabPane> 

但是,您的fooTabPage.fxml文件將可能是更可重複使用的,如果你不承擔其層次結構將被放入選項卡窗格(儘管這個級別的設計真的取決於你)。因此,將實例的根元素例如fooTabPage.fxml實例化可能更有用。

<?xml version="1.0" encoding="UTF-8"?> 
<!-- imports .... --> 
<BorderPane fx:controller="..." xmlns:fx="http://javafx.com/fxml/1"> 
    <!-- define content here... --> 
</BorderPane> 

,做(在你提供的鏈接),使得它更易於閱讀

<TabPane> 
    <tabs> 
     <Tab title="..."> 
      <content> 
       <fx:include source="fooTabPane.fxml" /> 
      </content> 
     </Tab> 
    </tabs> 
</TabPane> 
相關問題