【问题标题】:JavaFX Combobox listener for user changes only仅用于用户更改的 JavaFX Combobox 侦听器
【发布时间】:2018-01-31 10:06:28
【问题描述】:

我尝试在 ComboBox 上实现一个侦听器,该侦听器验证用户的选择并在选择无效时将其重置为之前的值。

我现在的问题是 valueProperty 或 selectedItemProperty 上的侦听器也可以识别以编程方式进行的更改,例如当用户选择另一个实体时,该实体随后会更改 ComboBox 值。

有没有办法实现只监听用户提交的更改的监听器?

        stateComboBox.valueProperty().addListener(new ChangeListener<State>() {

        @Override
        public void changed(ObservableValue<? extends State> observable, State oldValue,
                State newValue) 
        {
            if(stateCheckActive==false) return;
            if(newValue==null||oldValue.equals(newValue)) return;

            currentDocument.getBean().setStatus(oldValue);      

            if(service.changeStateAllowed(currentDocument.getBean(), newState.getId().getNr(), true))
            {
                stateCheckActive=false;

                newDocument=service.updateDocument(currentDocument.getBean());
                currentDocument.setBean(newDocument);

                stateCheckActive=true;
            }
            else 
            {
                Platform.runLater(new Runnable() {

                    @Override
                    public void run() 
                    {
                        stateCheckActive=false;
                        statusComboBox.setValue(oldValue);
                        stateCheckActive=true;
                    }
                });

            }

        }
    });

【问题讨论】:

  • 你能提供一些代码吗?
  • 没有 .. 你为什么需要它?程序化的改变只产生有效的改变,所以不管验证器是否在运行,它都会通过
  • 问题是一个有效值会触发对数据库的更新并重新加载实体,这会导致死锁,因为 ComboBox 值再次更改。我想我可能会尝试使用标志,因为似乎没有用户选择事件。
  • 听起来您未显示的代码有问题 - 请阅读 stackoverflow.com/help/mcve 并采取相应措施

标签: javafx javafx-8


【解决方案1】:

你需要这样的东西吗?

public class Controller implements Initializable {

    @FXML
    private ComboBox<String> comboBox;

    private ChangeListener<? super String> listener = (observable, oldValue, newValue) -> {
        if (!newValue.matches("[A-Z]*")) { // put your validation here
            comboBox.getSelectionModel().selectedItemProperty().removeListener(getListener());
            Platform.runLater(() -> {
                comboBox.getSelectionModel().select(oldValue);
                comboBox.getSelectionModel().selectedItemProperty().addListener(getListener());
            });
        }
    };

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        ObservableList<String> items = FXCollections.observableArrayList();
        items.add("VALID");
        items.add("MATCHES");
        items.add("NotMatches");
        items.add("RandomValue");
        comboBox.setItems(items);
        comboBox.getSelectionModel().select(0);
        comboBox.getSelectionModel().selectedItemProperty().addListener(getListener());
    }

    private ChangeListener<? super String> getListener() {
        return listener;
    }

}

【讨论】:

  • 当心 - 无论你想用 runlater 实现什么,它都是不可靠的:它只保证它“稍后”运行而不指定它是什么!!
  • 你是对的,但是代码片段不能在正确的时间执行的可能性较小,我真的没有看到任何可能导致严重问题的情况,但我接受任何建议。
  • 我认为 OP 在他的设置中做错了什么,所以不需要抓住稻草 ;) 我个人的规则是永远不要在 fx 上下文中使用 runlater,因为你根本不知道它什么时候会发生.
  • 但是当我们谈论“何时”时,它在几毫秒的范围内,在大多数情况下这并不重要,尤其是在没有 1k+ 的 JavaFx 应用程序中用户等等。有几个地方我无法避免使用它。一种情况是这个答案,我没有找到更好的解决方案来防止用户在出现问题时选择错误的项目。如果您知道这个问题的任何更好的解决方案,我也将不胜感激:)
  • 但您正在尝试解决 OP 没有的问题(至少在我阅读时) - 验证似乎没问题,但如果重新加载组合就会抛出 .. as对于你对 runlater 的使用,我很高兴它对你有用,但也很高兴我不必维护你用它编写的任何代码
猜你喜欢
  • 2015-07-21
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 1970-01-01
  • 2019-06-04
  • 1970-01-01
  • 2019-03-08
  • 1970-01-01
相关资源
最近更新 更多