2017-07-19 66 views
0

我有看法,並有ListViewPane。我想補充控制器爲ListView的項目,當我點擊ListView的元素之一,集Pane的內容,它的控制器內容,Javax:ListView:通過選擇ListView中的項目加載控制器

比如我有FruitsControllerVegetablesController,當然還有相應的.fxml爲每個控制器,當我點擊第一個元素設置Pane的元素tableView的水果,否則與蔬菜tableview。我嘗試了whith <fx:include source=Fruits.fxml>等,但我不知道如何切換內容,以及如何在ListView中將自定義名稱顯示爲元素名稱。那麼你有什麼想法嗎?

編輯:

,我發現這裏的部分和How can I Populate a ListView in JavaFX using Custom Objects?這裏JavaFX - ListView Item with an Image Button 解決方案,但問題仍然存在,我不知道如何以及在何處把<fx:include>標籤,加載它,當我點擊一個項目。

+0

這可能最好不要用''來完成。只需向列表視圖的選擇模型註冊監聽器,並在控制器中選擇更改時加載新的FXML。 –

+0

是的,這是我的解決方案,但我有9-10項,並且列表隨着時間增長,所以我認爲有一種更簡單的方法,在每次添加新的時候都不寫入加載程序項目列表。你爲什麼說「最好不要這樣做」?這是一種糟糕的方式,或者僅僅是不可能的? – Sunflame

+0

不知道我明白。您只需要一個監聽器來選擇,然後根據所選內容選擇FXML文件。然後*爲該FXML文件創建一個加載器並加載它。 (我想我不明白「寫入」加載程序的含義。)如果使用'',您基本上必須加載所有可能的FXML文件,並以某種方式隱藏不想顯示的文件,這會更加複雜,並且會一直將所有這些UI保存在內存中。也許如果你不能以簡單的方式使用監聽器發佈一些代碼來展示你如何去做。 –

回答

1

您只需向列表視圖的選擇模型註冊偵聽器,並在選擇更改時加載相應的視圖。

例如,假設你在FXML有

public class View { 

    private final String name ; 
    private final Class<?> controllerType ; 

    // You could assume that the resource is name+".fxml" if you want to rely on conventions like that 
    // That would eliminate the need for another field here, but would prevent 
    // e.g. names with whitespace etc. 
    private final String resource ; 

    public View(String name, Class<?> controllerType, String resource) { 
     this.name = name ; 
     this.controllerType = controllerType ; 
     this.resource = resource ; 
    } 

    public String getName() { 
     return name ; 
    } 

    public Class<?> getControllerType() { 
     return controllerType ; 
    } 

    public String getResource() { 
     return resource ; 
    } 

    @Override 
    public String toString() { 
     return name ; 
    } 
} 

然後:

<!-- imports, namespaces omitted --> 

<BorderPane fx:id="root" fx:controller="app.MainController" ... > 
    <left> 
     <ListView fx:id="selector"/> 
    </left> 
</BorderPane> 

,並在控制器:

package app ; 

public class MainController { 

    @FXML 
    private BorderPane root ; 

    @FXML 
    private ListView<View> selector ; 

    public void initialize() { 
     selector.getSelectionModel().selectedItemProperty().addListener((obs, oldView, newView) -> { 
      if (newView == null) { 
       root.setCenter(null); 
      } else { 
       // assumes each FXML is in the same package as its controller 
       // (which I think is a nice way to organize things) 
       FXMLLoader loader = new FXMLLoader(newView.getControllerType().getResource(newView.getResource())); 
       try { 
        root.setCenter(loader.load()); 
       } catch (IOException exc) { 
        // unrecoverable... 
        throw new UncheckedIOException(exc); 
       } 
      } 
     }); 

     selector.getItems().addAll(
      new View("Fruits", FruitsController.class, "Fruits.fxml"), 
      new View("Vegetables", VegetablesController.class, "Vegetables.fxml") 
     ); 
    } 
} 

如果所有的控制器都具有共同的功能,可以使它們實現一個通用接口(例如ProductsController),並檢索當前控制器f加載新的FXML後,從ProductsController currentController = loader.getController();開始從加載程序。 (在這種情況下,您也可以將View中的controllerType更改爲Class<? extends ProductsController>)。

+0

是的,就像你寫的一樣,我有一個由所有控制器實現的接口,所以我認爲這是我將使用的解決方案,它使用起來更加簡單和易於理解。 – Sunflame

+0

@Sunflame你可以讓'View'成爲一個枚舉,如果你願意並且仍然做同樣的事情,當然。 –

+0

我會更好地使用這個類,但是我認爲我必須使用這個資源,因爲我的_names_被翻譯成多種語言,並且在單詞之間也有空格,所以如果我理解正確,我不能用你在上面的註釋中寫的方式_resource_, – Sunflame