2016-11-16 198 views
0

需要您的幫助! 這可能是更多的設計觀點,但我使用這個模式遍佈我的應用程序,所以想要得到一個想法。JavaFX。從另一個控制器訪問一個控制器數據

附帶示例屏幕截圖。 http://imgur.com/a/fuD5D

我的問題: 我有一個BorderPane這是一種根容器的在我的情況(RootBorderPane.fmxl,RootBorderPaneController.java)。該視圖是使用場景構建器設計的。我將使用左側作爲導航面板,並根據左側的選擇,我將在RootBorderPane的中心區域加載一個新視圖。我有其他類似的視圖(View1.fxml,View2.fxml,View3.fxml等)(使用場景構建器設計)和相應的控制器(View1Controller.java,View2Controller.java,View3Controller.java等)。 View1,View2,View3包含自己的TableViews。 現在我在RootBorderPane的左邊有幾個按鈕(Button1,Button2,Button3等),如果我點擊Button1,然後我應該加載我的View1(View1.fxml)並將其設置在RootBorderPane中心區域。

我點擊「按鈕1」,在按鈕上點擊我加載View1並將其設置在RootBorderPane的中心。這個邏輯是在RootBorderPaneController.java裏面的,包含一個TableView和表視圖的數據在View1的控制器(View1Controller.java)的initializable()方法上加載和設置。 我能夠完成上面所說的所有操作。

問題: 我有導航面板上的添加和刪除按鈕,這些按鈕應根據在View1的tableview上選擇的記錄啓用/禁用。 (如果在桌面視圖上選擇了一個記錄,則應該啓用刪除按鈕否則在沒有在桌面視圖上選擇記錄的情況下應該啓用添加按鈕)

直接或間接地,我的問題擱置爲從另一個控制器訪問一個控制器。有沒有什麼優雅的設計方法可以做到這一點,而不是在其他控制器中保留1個控制器的參考。

由於提前

+0

見http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx –

回答

0

一個方法,讓你訪問你的subPanes(View_1 ... View_n)的控制器是你的根窗格做加載它們。

// Load root layout from fxml file. 
FXMLLoader loader = new FXMLLoader(); 
rootLayout = loader.load(getClass().getResource("BorderPane.fxml").openStream()); 

BorderPaneController bpc = (BorderPaneController) loader.getController(); 

List<Pane> subPaneList = new ArrayList<>(); 
for (int i = 0; i < 30; i++) { 
    loader = new FXMLLoader(); 
    loader.setLocation(MainApp.class.getResource("View" + i + ".fxml")); 
    subPaneList.add((Pane) loader.load()); 
} 
bpc.setSubPaneList(subPaneList); 

// Show the scene containing the root layout. 
Scene scene = new Scene(rootLayout); 
primaryStage.setScene(scene); 
primaryStage.show(); 

現在你只需要在你的BPC控制器setSubPaneList(..)方法,你將能夠訪問你的subPanes的公共方法(例如的getter/setter)

+0

你不應該有一個循環,只是按鈕號加載正確的視圖。 – pdem

0

看來你加載動態使用FXML裝載機查看,所以這裏是使用它的規則:

  1. 不要使用FXMLLoader的靜態方法,intanciate的FXMLLoader對它有更多的選擇(即控制器&節點實例)
  2. 從主控制器獲取由FXMLLoader給出的子控制器實例。
  3. 選擇在父子控制器之間操作的常用方法:我提出了一個selectedProperty()方法。
  4. 獲取從一個接口這個屬性,因此它是所有子控制器訪問

我用房產控制器之間進行操作,你的情況TableView中的selectedProperty應該是理想的解決方案:你可以有選擇的實例,並且您有選擇/取消選擇的事件,可以以兩種方式使用:只需綁定它,或者添加在tableView中完成的更改的偵聽器。
對於這種情況,綁定就足夠了。

該解決方案涉及許多文件,所以這裏是主要技巧:從主控制器獲取當前子項的selectedProperty實例,並將其綁定到按鈕的visibleProperty以顯示它。

buttonOpen.disableProperty().bind(controller.selectedProperty().isNull()); 

你將再次需要一個selectedProperty在開啓按鈕的代碼

public void open(){ 
//TODO open in a view 
System.out.println("open the object"+selectedProperty().get() 
} 

全部來源:

Java文件

/** 
* App launch 
*/ 
public class SOFx extends Application{ 

    public static void main(String[] args) { 
    launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
    primaryStage.setTitle ("SO test"); 
    //static loading for index, don't need the controller. 
    Parent root = FXMLLoader.load(getClass().getResource("Index.fxml"),null); 
    Scene scene = new Scene(root); 
    primaryStage.setMaximized(true); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
    } 
} 

/** 
* Main Controller 
*/ 
public class IndexController { 


    @FXML 
    private BorderPane root; 

    @FXML 
    private Button buttonOpen; 

    private ObjectProperty<Object> selectedProperty; 

    public FXMLLoader loadFXML(URL url, ResourceBundle resources){ 
    FXMLLoader fxmlLoader = new FXMLLoader(); 
    fxmlLoader.setLocation (url); 
    fxmlLoader.setResources(resources); 
    try { 
     fxmlLoader.load(); 
     return fxmlLoader; 
    } catch (IOException e) { 
     e.printStackTrace(System.err); 
     throw new IllegalStateException(e); 
    } 
    } 

    public void button1(){ 
    FXMLLoader loadFXML = loadFXML(getClass().getResource("View1.fxml"),null); 
    root.setCenter(loadFXML.getRoot()); 
    ICenterController controller = (ICenterController) loadFXML.getController(); 
    selectedProperty = controller.selectedProperty(); 
    buttonOpen.disableProperty().bind(selectedProperty.isNull()); 
    } 

    public void open(){ 
    //TODO open in a view 
    System.out.println("open the object"+selectedProperty.get()); 
    } 

} 

/** 
* Interface of Center controllers 
*/ 
public interface ICenterController { 
ObjectProperty<Object> selectedProperty(); 
} 



/** 
* Child controller 
*/ 
public class View1Controller implements ICenterController { 

    private static final ObjectProperty<Object> selectedProperty = new SimpleObjectProperty(); 

    @Override 
    public ObjectProperty<Object> selectedProperty() { 
    return selectedProperty; 
    } 

    /** 
    * simulate TableView selection/deselection 
    */ 
    public void select(){ 
    selectedProperty.set(new Object()); 
    } 

    public void deselect(){ 
    selectedProperty.set(null); 
    } 

} 

FXML文件,我不做一個完整的TableView,我用按鈕模擬它

Index.fxml

<BorderPane xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" 
     fx:controller="pdem.stackoverflow.IndexController" fx:id="root"> 

     <left> 
      <VBox> 
       <Button onAction="#button1" text="view1"/> 
       <Button fx:id="buttonOpen" text="open"/> 
      </VBox> 

     </left> 


    </BorderPane> 

View1.fxml

<VBox xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="pdem.stackoverflow.View1Controller" > 
      <Button onAction="#select" text="select"/> 
      <Button onAction="#deselect" text="deselect"/> 
</VBox> 
相關問題