首页 > 解决方案 > JavaFX:如果节点等于节点

问题描述

我有一个像这样的简单 JavaFX 程序:
布局

当我点击第一个按钮时,它将 content1 放在分屏的右侧。当我点击 button2 时,它会将 content2 放在右侧(表现得应该如此)。

但是当例如 content2 中有一个 TextField 并且我再次单击 button2 时,它会重置。
如何检查我是否已经在 content2 中?

控制器.java:

@FXML private SplitPane splitpane;
@FXML private Node content;


@FXML
public void initialize() {
    changeContent(new ContentA());
}



@FXML
public void onMenuClickA(ActionEvent event) {
    changeContent(new ContentA());
}
@FXML
public void onMenuClickB(ActionEvent event) {
    changeContent(new ContentB());
}




private void changeContent(Node node) {
    if (node.equals(content)) {        // <---- Not working
        System.out.println("Same");
    }
    List<Node> splitpaneItems = splitpane.getItems();
    splitpaneItems.set(splitpaneItems.indexOf(content), node);
    content = node;
}

内容A.java:

public class ContentA extends HBox {

public ContentA() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/contents/Test1.fxml"));

    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);

    try {
        fxmlLoader.load();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

标签: javajavafxequals

解决方案


有许多可能的解决方案,具体取决于您想要的确切行为。

如果您不想重置单个组件,只需在initialize()方法中预加载它们,并将它们保存到实例变量中:

public class Controller {

    @FXML private SplitPane splitpane;

    private ContentA contentA ;
    private ContentB contentB ; 

    private int contentIndex ;        

    @FXML
    public void initialize() {
        contentA = new ContentA();
        contentB = new ContentB();
        contentIndex = splitPane.getItems().size() ;
        splitPane.getItems().set(contentIndex, contentA);
    }



    @FXML
    public void onMenuClickA(ActionEvent event) {
        changeContent(contentA);
    }
    @FXML
    public void onMenuClickB(ActionEvent event) {
        changeContent(contentB);
    }

    private void changeContent(Node node) {
        splitpaneItems.set(contentIndex, node);
    }

}

另一方面,如果您想在加载内容时“重置”内容,但又想阻止用户重新加载当前内容,您可以禁用最近按下的按钮:

public class Controller {

    @FXML private SplitPane splitpane;
    @FXML private Button buttonA ;
    @FXML private Button buttonB ;

    private int contentIndex ;        


    @FXML
    public void initialize() {
        buttonA.setDisable(true);
        contentIndex = splitPane.getItems().size() ;
        changeContent(new ContentA()); 
    }



    @FXML
    public void onMenuClickA(ActionEvent event) {
        buttonA.setDisable(true);
        buttonB.setDisable(false);
        changeContent(new ContentA());
    }
    @FXML
    public void onMenuClickB(ActionEvent event) {
        buttonA.setDisable(false);
        buttonB.setDisable(true);
        changeContent(new ContentB());
    }




    private void changeContent(Node node) {
        splitpaneItems.set(splitpaneItems.indexOf(content), node);
    }

}

最后,如果您希望能够控制不同内容的不同行为(例如,总是重新加载内容 A,从不重新加载内容 B),您需要使用一个变量来跟踪内容的状态。一个enum适用于此:

public class Controller {

    private ContentB contentB  ;


    public enum Content {
        A(() -> new ContentA()),
        B(() -> contentB) ;


        private final Supplier<Node> nodeLoader ;

        Content(Supplier<Node> nodeLoader) {
            this.nodeLoader = nodeLoader ;
        }

        public Node getContent() {
            return nodeLoader.get();
        }
    }

    private Content currentContent ; 


    @FXML
    public void initialize() {

        contentB = new ContentB();

        contentIndex = splitPane.getItems().size() ;
        changeContent(Content.A);
    }



    @FXML
    public void onMenuClickA(ActionEvent event) {
        changeContent(Content.A);
    }
    @FXML
    public void onMenuClickB(ActionEvent event) {
        changeContent(Content.B);
    }

    private void changeContent(Content content) {
        this.currentContent = content ;
        splitpaneItems.set(contentIndex, content.getContent());
    }

}

推荐阅读