2015-05-16 94 views
0

我有兩個帶控制器的* .fxml表單。首先是Window,其次是ProductPane。JavaFX TabPane選擇無法正常工作

簡化Window.fxml是:

<BorderPane prefWidth="650.0" prefHeight="450.0" fx:controller="package.WindowController"> 
    <center> 
     <TabPane fx:id="tabsPane"> 
      <tabs> 
       <Tab fx:id="productsTab" text="Products"/> 
       <Tab fx:id="warehouseTab" text="Warehouse"/> 
       <Tab fx:id="saleTab" text="Sale"/> 
      </tabs> 
     </TabPane> 
    </center> 
</BorderPane> 

控制器Window.fxml:

public class WindowController { 
    @FXML 
    private TabPane tabsPane; 

    @FXML 
    private Tab productsTab; 

    @FXML 
    void initialize() { 
     sout("Main Window initialization..."); 

     tabsPane.getSelectionModel().selectedIndexProperty().addListener((e, o, n) -> { 
      sout("Changed to " + n); 
     }); 

     tabsPane.getSelectionModel().selectedItemProperty().addListener((e, o, n) -> { 
      sout("New item: " + n); 
      // Load ProductPane content: 
      if(n == productsTab) { 
       try { 

        Parent p = FXMLLoader.load(getClass().getResource("productPane.fxml")); 
        n.setContent(p); 

       } catch(IOException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }); 

     sout("Select first item..."); 
     tabsPane.getSelectionModel().selectFirst(); 

     // This methods also don't work 
     // tabsPane.getSelectionModel().clearAndSelect(); 
     // tabsPane.getSelectionModel().select(productTab); 
     // tabsPane.getSelectionModel().select(0); 
    } 
} 

的問題是:當我加載Window.fxml在main()並運行,appearse窗口空的第一個標籤。

調試輸出:

Main Window initialization... 
Select first item... 

但ProductPane沒有加載和聽衆不叫。如果我在Window中的選項卡之間切換,則會觸發偵聽器並正確加載產品選項卡。

有什麼問題?

回答

1

您在選項卡窗格的選擇模型中添加了ChangeListener,當選擇更改時,該選項模型會被通知。默認情況下,選中第一個選項卡,因此在添加更改偵聽器時,第一個選項卡已被選中。這意味着當您撥打selectFirst()時,選擇不會改變(因爲您要求選擇已選擇的選項卡),因此不會通知監聽者。

該解決方案有點難看:如果您在添加偵聽器時選擇了產品選項卡,則只需要直接加載您的產品選項卡內容。我會因素的代碼到一個單獨的方法,以避免過多的重複:

@FXML 
void initialize() { 
    System.out.println("Main Window initialization..."); 

    tabsPane.getSelectionModel().selectedIndexProperty().addListener((e, o, n) -> { 
     System.out.println("Changed to " + n); 
    }); 

    tabsPane.getSelectionModel().selectedItemProperty().addListener((e, o, n) -> { 
     System.out.println("New item: " + n); 
     // Load ProductPane content: 
     if(n == productsTab) { 
      loadProductsTab(); 
     } 
    }); 

    if (tabPane.getSelectionModel().getSelectedItem() == productsTab) { 
     loadProductsTab(); 
    } 
} 

private void loadProductsTab() { 
    try { 

     Parent p = FXMLLoader.load(getClass().getResource("productPane.fxml")); 
     productsTab.setContent(p); 

    } catch(IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

如果你發現你需要這種功能有很多,你可能有興趣在ReactFX框架,(我認爲)已建成處理這些情況的功能。

+0

感謝您的解釋。這是個好主意。但是我已經使用了另一種方法:直接在Window.fxml中包含ProductPane.fxml並使用嵌入式窗格和控制器。本文有助於:[Oracle文檔](https://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm) – Ivan