首页 文章

JavaFX的 . 从另一个控制器访问一个控制器数据

提问于
浏览
0

需要你的帮助!这可能更多的是设计视角,但我在我的应用程序中使用这种模式,所以想得到一个想法 .

附加示例屏幕截图 . 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中心区域 .

我单击“Button1”,在按钮上单击我加载了View1并将其设置在RootBorderPane的中心 . 这个逻辑在RootBorderPaneController.java里面.View1包含一个TableView,并且在View1的控制器(View1Controller.java)的initializable()方法上加载和设置表视图的数据我能够实现上述所有说法 .

问题:我在导航面板上有添加和删除按钮,这些按钮应根据在View1的tableview上选择的记录启用/禁用 . (如果在桌面视图上选择了记录,则应启用删除按钮,否则如果在桌面视图中未选择任何记录,则应启用“添加”按钮)

直接或间接地我的问题搁置到从另一个控制器访问一个控制器 . 是否有任何优雅的设计方法来做到这一点,而不是在另一个控制器中保留1个控制器的参考 .

提前致谢

2 回答

  • 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

    您似乎使用FXML Loader动态加载View,因此以下是使用它的规则:

    • 不要使用FXMLLoader的静态方法,使FXMLLoader拥有更多选项(即控制器和节点实例)

    • 从主控制器获取FXMLLoader给出的子控制器实例 .

    • 选择在父子控制器之间操作的常用方法:我提出了一个selectedProperty()方法 .

    • 从接口获取此属性,以便所有子控制器都可以访问它

    我使用Property在控制器之间操作,在你的情况下,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>
    

相关问题