2016-11-16 102 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> 
相关问题