我看过this article on ListenerHandles,但我无法理解如何在我的代码中实现它。我有ChangeListener
我分配给CheckBoxes
。我需要更改CheckBoxes
的值而不Listeners
注意到它。
我创建CheckBoxes
的代码:
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);
}
ChangeListener
代码:
private ChangeListener<Boolean> checkBoxListener(CheckBox checkBox) {
return new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean selected) {
if (selected) {
System.out.println("CheckBox got selected");
} else {
System.out.println("CheckBox got deselected");
}
}
};
}
需要在没有Listener
注意的情况下完成的代码:
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));
}
}
Listener
仍然注意到我通过此功能取消选择CheckBox
。有人可以解释我如何在我的代码中实现ListenerHandle
方法吗?
非常感谢您的回答。我调整了ChangeListener
,以便我可以从CheckBox
获取对象:
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");
}
};
答案 0 :(得分:0)
首先,注意几点:
checkBoxListener()
都会创建一个不同的侦听器。因此,您尝试删除的侦听器不是您最初添加的侦听器,因此对removeListener(...)
的调用不执行任何操作。更糟糕的是,当您尝试恢复原始内容时,稍后会添加不同的侦听器。因此,您应该发现在调用deselectCheckBoxes()
方法后选中复选框会多次调用侦听器。无论如何,假设你出于某些原因确实需要这个,正如我所理解的那样,意图是你会做这样的事情:
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 ;
}
}
}
然后您可以将其用作
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();
和&#34;关闭&#34;处理,你会做
// ignore this change:
handle.detach();
checkBox.setSelected(false);
handle.attach();
请注意,要使其工作,您仍然需要保留对句柄的引用(您不再需要保持对属性或节点的单独引用,并保持它们&#34;已连接&#34;) 。在您的情况下,由于您有多个复选框,因为您有多个复选框和多个侦听器,您需要以下内容:
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);
}
请注意,如果要取消选中(并忽略)特定复选框,则必须知道哪个句柄属于该特定复选框。你可以用Map
或类似的方法做到这一点,但是那时你几乎没有什么收获,而只是简单地保留对听众的引用并删除它们。