JavaFX:检索节点

JavaFX:检索节点,javafx,fxml,Javafx,Fxml,我有两个FXML文档,每个文档代表一个视图,让我们称它们为View1和View2,我将它们分别放在选项卡中(选项卡1和选项卡2)的选项卡窗格中 现在在View1的Controller1中,我有一个事件将我的TabPane的selectedItem从Tab1切换到Tab2。我的问题是如何从Controller1 总的来说。如何在Javafx中检索某个节点 编辑 视图1 主视图 <TabPane fx:id="tabPane" fx:controller="controllers.MainCo

我有两个
FXML
文档,每个文档代表一个视图,让我们称它们为
View1
View2
,我将它们分别放在
选项卡
中(
选项卡1
选项卡2
)的
选项卡窗格中

现在在
View1
Controller1
中,我有一个事件将我的
TabPane
selectedItem
Tab1
切换到
Tab2
。我的问题是如何从
Controller1

总的来说。如何在
Javafx
中检索某个
节点

编辑 视图1

主视图

<TabPane fx:id="tabPane" fx:controller="controllers.MainController"/>
您应该创建一个“视图模型”,它封装视图的当前状态,并与每个控制器共享它。然后从主控制器观察,并做出相应的响应

例如:

public class ApplicationState {

    private final StringProperty currentViewName = new SimpleStringProperty();

    public StringProperty currentViewNameProperty() {
        return currentViewName ;
    }

    public final String getCurrentViewName() {
        return currentViewNameProperty().get();
    }

    public final void setCurrentViewName(String viewName) {
        currentViewNameProperty().set(viewName);
    }
}
现在您可以这样做了(注意,我在这里也删除了多余的重复代码):

请注意,由于控制器没有arg构造函数,因此我使用
loader.setController(…)
在代码中设置它们。这意味着您必须从view1和view2的fxml文件中删除
fx:controller
属性,例如,您的view1.fxml变为:


这种设计的优点是,当你的老板在8个月后走进你的办公室,说“客户不喜欢选项卡窗格,用一次只显示一个屏幕的东西来代替它”时,很容易做出这样的更改,因为一切都被适当地解耦了。(您只需更改主视图及其控制器,其他任何视图或控制器都不会更改。)如果将选项卡窗格暴露给所有其他控制器,则必须找到您访问过的所有位置才能进行类似更改。

您应该创建一个“视图模型”它封装视图的当前状态,并与每个控制器共享。然后从主控制器观察,并做出相应的响应

例如:

public class ApplicationState {

    private final StringProperty currentViewName = new SimpleStringProperty();

    public StringProperty currentViewNameProperty() {
        return currentViewName ;
    }

    public final String getCurrentViewName() {
        return currentViewNameProperty().get();
    }

    public final void setCurrentViewName(String viewName) {
        currentViewNameProperty().set(viewName);
    }
}
现在您可以这样做了(注意,我在这里也删除了多余的重复代码):

请注意,由于控制器没有arg构造函数,因此我使用
loader.setController(…)
在代码中设置它们。这意味着您必须从view1和view2的fxml文件中删除
fx:controller
属性,例如,您的view1.fxml变为:



这种设计的优点是,当你的老板在8个月后走进你的办公室,说“客户不喜欢选项卡窗格,用一次只显示一个屏幕的东西来代替它”时,很容易做出这样的更改,因为一切都被适当地解耦了。(您只需更改主视图及其控制器,其他任何视图或控制器都不会更改。)如果将选项卡窗格暴露给所有其他控制器,则必须找到您访问过的所有位置才能进行类似更改。

通常,您不应该从控制器中的一个视图访问另一个视图的控件。相反,改变一些可观察的数据,并在需要的地方观察这些数据。如果你能用一个例子来演示你的问题,那么在这里提供一个真实的答案会更容易。谢谢你的编辑,但是你能校对一下并修正打字错误吗?
openView1()
不应该是
openView2()
?我假设MainView中的
mainController
应该是
mainController
?一般来说,您不应该从控制器中的一个视图访问另一个视图的控件。相反,改变一些可观察的数据,并在需要的地方观察这些数据。如果你能用一个例子来演示你的问题,那么在这里提供一个真实的答案会更容易。谢谢你的编辑,但是你能校对一下并修正打字错误吗?
openView1()
不应该是
openView2()
?我假设MainView中的
mainController
应该是
mainController
?JavaFX可能在某些方面有所欠缺,但我认为它最好的一面是它以某种方式迫使您使用MVC模型。非常impressive@m0skit0是(至少有一个MVC/MVP/MVVM/etc)。大画面的设计非常好,即使一些细节可能需要一些调整。从长远来看,这可能是一个好迹象。JavaFX可能在某些方面有所欠缺,但它最好的一面是,它以某种方式迫使您使用MVC模型。非常好impressive@m0skit0是(至少有一个MVC/MVP/MVVM/etc)。大画面的设计非常好,即使一些细节可能需要一些调整。从长远来看,这可能是一个好迹象。
public class MainController implements Initializable {

@FXML
public TabPane tabPane;

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    try {
        tabPane.getTabs().add(createView1Tab());
        tabPane.getTabs().add(createView2Tab());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

protected Tab createView1Tab() throws IOException {
    Tab tab = new Tab();
    tab.setContent(FXMLLoader.load(getClass().getResource("/views/View1.fxml")));
    return tab;
}

protected Tab createView2Tab() throws IOException {
    Tab tab = new Tab();
    tab.setContent(FXMLLoader.load(getClass().getResource("/views/View2.fxml")));
    return tab;
}
}
public class ApplicationState {

    private final StringProperty currentViewName = new SimpleStringProperty();

    public StringProperty currentViewNameProperty() {
        return currentViewName ;
    }

    public final String getCurrentViewName() {
        return currentViewNameProperty().get();
    }

    public final void setCurrentViewName(String viewName) {
        currentViewNameProperty().set(viewName);
    }
}
public class MainController implements Initializable {

    @FXML
    public TabPane tabPane;

    private final ApplicationState appState = new ApplicationState();
    private final Map<String, Tab> views = new HashMap<>();

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        try {
            tabPane.getTabs().add(createViewTab("View1", new Controller1(appState)));
            tabPane.getTabs().add(createViewTab("View2", new Controller2(appState)));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        appState.currentViewNameProperty().addListener((obs, oldView, newView) ->
            tabPane.getSelectionModel().select(views.get(newView)));
        appState.setCurrentViewName("View1");
    }

    protected Tab createViewTab(String viewName, Object controller) throws IOException {
        Tab tab = new Tab();
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/"+viewName+".fxml"));
        loader.setController(controller);
        tab.setContent(loader.load());
        views.put(viewName, tab);
        return tab;
    }


}
public class Controller1{

    private final ApplicationState appState ;

    public Controller1(ApplicationState appState) {
        this.appState = appState ;
    }

    public void openView2(){
        appState.setCurrentViewName("View2");
    }
}