Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JavaFX中使用ListenerHandle?_Javafx_Changelistener - Fatal编程技术网

如何在JavaFX中使用ListenerHandle?

如何在JavaFX中使用ListenerHandle?,javafx,changelistener,Javafx,Changelistener,我读过,但我不明白如何在代码中实现它。我有一个ChangeListener,我将它分配给我的复选框。我需要更改复选框的值,而不让侦听器注意到它 创建复选框的我的代码: for (int i = 0; i<2; i++) { CheckBox checkBox = new CheckBox(); checkBox.setText("CheckBox "+(i+1)); checkBox.setAlignment(Pos.TOP_LEFT); checkBox

我读过,但我不明白如何在代码中实现它。我有一个
ChangeListener
,我将它分配给我的
复选框
。我需要更改
复选框的值,而不让
侦听器注意到它

创建
复选框的我的代码

for (int i = 0; i<2; i++) {
    CheckBox checkBox = new CheckBox();
    checkBox.setText("CheckBox "+(i+1));
    checkBox.setAlignment(Pos.TOP_LEFT);

    checkBox.selectedProperty().addListener(checkBoxListener(checkBox));

    myVBox.getChildren().add(checkBox);
    }
需要在没有侦听器注意的情况下完成的代码:

public void deselectCheckBoxes(){
      for(Node node : myVBox.getChildren()){
            CheckBox checkBox = (CheckBox) node;
            System.out.println("Removing listener");
            checkBox.selectedProperty().removeListener(checkBoxListener(checkBox));

            checkBox.setSelected(false);

            System.out.println("Adding listener back");
            checkBox.selectedProperty().addListener(checkBoxListener(checkBox));
       }
}
侦听器
仍然注意到我正在通过此函数取消选中
复选框
。有人能解释一下我如何在代码中实现
ListenerHandle
方式吗

非常感谢你的回答。我调整了
ChangeListener
,以便可以从我的
复选框中获取对象:

ChangeListener<Boolean> listener = (obs, wasSelected, isNowSelected) -> {
            if (isNowSelected) {
                BooleanProperty booleanProperty = (BooleanProperty) obs;
                CheckBox checkBox = (CheckBox)booleanProperty.getBean();

                System.out.println("Selected: "+(Bank)checkBox.getUserData());
            } else {
                System.out.println("Not selected");
            }
        };
ChangeListener侦听器=(obs、wasSelected、isNowSelected)->{
如果(现在已选定){
BooleanProperty=(BooleanProperty)obs;
复选框=(复选框)booleanProperty.getBean();
System.out.println(“选中:”+(银行)复选框.getUserData();
}否则{
系统输出打印项次(“未选择”);
}
};
首先,请注意:

  • 您的代码无法工作,因为您的
    checkBoxListener()
    每次调用它时都会创建一个不同的侦听器。因此,您试图删除的侦听器不是您最初添加的侦听器,因此对
    removeListener(…)
    的调用不起任何作用。更糟糕的是,您稍后在尝试恢复原始侦听器时添加了不同的侦听器。因此,您应该发现在调用
    取消选中复选框()
    方法后选中复选框会多次调用侦听器
  • 对我来说,需要这样做通常是一个糟糕设计的标志。您真的不应该关心如何取消选中复选框(即通过编程或由用户取消选中)。控制器应该真正调用模型上的方法,以便模型与UI的状态同步。从这个角度来看,取消选中复选框的原因应该无关紧要
  • 注意,这个功能是由Tomas Mikula的“开箱即用”实现的。(基本上,您可以订阅“事件流”,其中可以包括对属性的更改流。您可以使这些流“可挂起”,并在特定操作期间挂起它们。)
  • 不管怎么说,假设你真的出于某种原因需要这个,我的理解是,目的是你会做这样的事情:

    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    
    public class ListenerHandle<T>  {
    
        private final ObservableValue<T> observable ;
        private final ChangeListener<? super T> listener ;
    
        private boolean attached ;
    
        public ListenerHandle(ObservableValue<T> observable, ChangeListener<? super T> listener) {
            this.observable = observable ;
            this.listener = listener ;
        }
    
        public void attach() {
            if (! attached) {
                observable.addListener(listener);
                attached = true ;
            }
        }
    
        public void detach() {
            if (attached) {
                observable.removeListener(listener);
                attached = false ;
            }
        }
    
    
    }
    
    请注意,要实现这一点,您仍然需要保留对句柄的引用(您不再需要保留对属性或节点的单独引用,并保持它们“连接”)。在您的情况下,因为您有多个复选框,因为您有多个复选框和多个侦听器,所以您需要以下内容:

    private List<ListenerHandle<Boolean>> checkBoxListenerHandles = new ArraryList<>();
    
    // ...
    
    ChangeListener<Boolean> listener = (obs, wasSelected, isNowSelected) -> {
        if (isNowSelected) {
            System.out.println("CheckBox got selected");
        } else {
            System.out.println("CheckBox got deselected");
        }
    }
    
    for (int i = 0; i<2; i++) {
        CheckBox checkBox = new CheckBox();
        checkBox.setText("CheckBox "+(i+1));
        checkBox.setAlignment(Pos.TOP_LEFT);
    
        ListenerHandle<Boolean> handle = new ListenerHandle<>(checkBox.selectedProperty(), listener);
        handle.attach();
        checkBoxListenerHandles.add(handle);
    
        myVBox.getChildren().add(checkBox);
    }
    

    请注意,如果要取消选择(并忽略)特定复选框,则必须知道哪个句柄属于该特定复选框。你可以用
    地图或类似的地图来实现这一点,但在这一点上,与简单地保留对听众的引用并删除它们相比,你几乎没有什么收获。

    谢谢你的回答。我目前正在学习哪种方式最适合处理听众。我需要将
    CheckBox
    对象传递给侦听器,基本上我需要访问连接到
    CheckBox
    内部侦听器的对象,就像
    CheckBox.getUserData()
    。我可以这样做吗?如果听起来有点太复杂了,我很抱歉。
        ChangeListener<Boolean> listener = (obs, wasSelected, isNowSelected) -> {
            if (isNowSelected) {
                System.out.println("Selected");
            }
            else {
                System.out.println("Not selected");
            }
    
        };
    
        ListenerHandle<Boolean> handle = new ListenerHandle<>(checkBox.selectedProperty(), listener);
        handle.attach();
    
    // ignore this change:
    handle.detach();
    checkBox.setSelected(false);
    handle.attach();
    
    private List<ListenerHandle<Boolean>> checkBoxListenerHandles = new ArraryList<>();
    
    // ...
    
    ChangeListener<Boolean> listener = (obs, wasSelected, isNowSelected) -> {
        if (isNowSelected) {
            System.out.println("CheckBox got selected");
        } else {
            System.out.println("CheckBox got deselected");
        }
    }
    
    for (int i = 0; i<2; i++) {
        CheckBox checkBox = new CheckBox();
        checkBox.setText("CheckBox "+(i+1));
        checkBox.setAlignment(Pos.TOP_LEFT);
    
        ListenerHandle<Boolean> handle = new ListenerHandle<>(checkBox.selectedProperty(), listener);
        handle.attach();
        checkBoxListenerHandles.add(handle);
    
        myVBox.getChildren().add(checkBox);
    }
    
    public void deselectCheckBoxes(){
    
       checkBoxListenerHandles.forEach(ListenerHandle::detach);
    
       for(Node node : myVBox.getChildren()){
            CheckBox checkBox = (CheckBox) node;
            checkBox.setSelected(false);
       }
    
       checkBoxListenerHandles.forEach(ListenerHandle::attach);
    
    }