我已经为这个问题困惑了一段时间,只是想看看其他人以前是否遇到过这个问题,或者我是否做错了什么。
给定一个javafx实现,其中我们使用一个组合框,其项是从ObservableArrayList
设置的,可以更新、修改、替换等。
package sample;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class Main extends Application {
ObservableList<String> theList = FXCollections.observableArrayList();
@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Sample");
FlowPane root = new FlowPane(Orientation.VERTICAL);
root.setVgap(20);
List<String> initialColors = Arrays.asList("red", "green", "blue", "black");
theList.addAll(initialColors);
ComboBox<String> theComboBox = new ComboBox<>();
theComboBox.setItems(theList);
theComboBox.setOnAction( event -> {
System.out.println(String.format("theComboBox action listener triggered, current value is %s", theComboBox.getValue()));
});
Button bttn1 = new Button("Press me");
bttn1.setOnAction(event -> {
List<String> someColors = Arrays.asList("red", "orange", "mauve", "pink", "blue", "salmon", "chiffon");
System.out.println("About to issue setAll against observable list");
theList.setAll(someColors);
});
root.getChildren().add(theComboBox);
root.getChildren().add(bttn1);
primaryStage.setScene(new Scene(root, 100, 150));
primaryStage.show();
System.out.println("Setting initial selection to "blue"");
theComboBox.setValue("blue");
}
public static void main(String[] args) {
launch(args);
}
}
我认为只有当用户通过直接操作更改组合框时,才应该触发操作事件,但我看到的是当Observalelist被修改时会触发事件。
我们使用的是javafx11.0.2版
我应该用Gloon将其作为bug记录吗?
EDIT:更新的示例
在本例中,您可以看到,无论何时通过setAll
修改底层数据,都会触发操作事件。如果操作事件有某种方式来区分它是来自直接的用户交互还是来自对底层数据的编程更改,那么这将是很好的。
其他奇怪的行为,如果您选择";黑色";然后点击";按我";按钮和组合框将选择粉红色,因为它在列表中的位置相同,但随后再次选择红色甚至粉红色,您将分别获得null、red、null和null、pink、null。
即使选择不再存在,我也希望组合框保持其值,而且我也不希望在修改可观察列表时触发这些事件-如果您需要/想要在修改可观测列表时侦听事件,则可以将侦听器直接附加到它。
为了总结这一点,请查看对该问题的评论以了解更多详细信息。
我们认为这是javafx11.0.2中的一个错误-我已经通过openjdk-jira提交了一份错误报告。
目前的一个解决方法是设置一个标志布尔变量,并且只有当它为true时才在侦听器中执行操作。
简单到添加:
private boolean actionEventsOn = true;
theComboBox.setOnAction( event -> {
if(actionEventsOn){
System.out.println(String.format("theComboBox action listener triggered, current value is %s", theComboBox.getValue()));
}
});
bttn1.setOnAction(event -> {
List<String> someColors = Arrays.asList("red", "orange", "mauve", "pink", "blue", "salmon", "chiffon");
System.out.println("About to issue setAll against observable list");
actionEventsOn = false;
theList.setAll(someColors);
actionEventsOn = true;
});
这样可以防止不必要地触发操作事件。