【问题标题】:setting listener Combobox JavaFX设置监听器组合框 JavaFX
【发布时间】:2017-05-25 20:46:04
【问题描述】:

您好,我对某些组合框有疑问。我有一个带有四个组合框的界面,它们使用相同的列表作为项目。我在其中一个组合框中添加了一个侦听器,我希望仅在我选择一个项目而不是在更改列表时完成该侦听器,但是使用此侦听器,当我从列表中删除一个项目时,他会自动再次运行

            class1.getSelectionModel().selectedItemProperty().addListener( (options, oldValue, newValue) ->{

            System.out.println(oldValue);
            System.out.println(newValue);

            class1.getItems().add(oldValue);
            class1.getItems().remove(newValue);

            });

所以最后他每次我执行删除时都会运行这个监听器,最终以错误结束

【问题讨论】:

  • 如果你删除了被选中的项目,那么显然选择将不得不改变。你到底想在这里发生什么? (为什么要更改列表中的选择?)
  • 我想在组合框值上显示我选择的项目,但我希望从列表中删除该项目,所以当我再次单击该组合框时,它将显示为选项已经被选中的那个

标签: java javafx combobox interface listener


【解决方案1】:

问题的出现基本上是因为您在处理该列表的更改时最终更改了可观察列表(选择模型的selectedItems)。这是API中的一个缺陷,imo。一种解决方法(hack)是使用过滤列表,并在Platform.runLater(...) 中更新列表上的谓词,以便在再次更改之前让第一次更改完成:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ComboBoxNoSelectedItem extends Application {

    @Override
    public void start(Stage primaryStage) {
        ObservableList<String> allItems = FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five");
        ComboBox<String> combo = new ComboBox<>();
        combo.setValue(allItems.get(0));
        FilteredList<String> items = allItems.filtered(item -> item != combo.getValue());
        combo.setItems(items);

        combo.valueProperty().addListener((obs, oldValue, newValue) -> Platform.runLater(() -> items.setPredicate(item -> item != newValue)));


        BorderPane root = new BorderPane();
        root.setTop(combo);
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

也许更简洁的方法是禁用显示当前所选项目的单元格,这与 UX 很接近,但并不完全相同:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ComboBoxNoSelectedItem extends Application {

    @Override
    public void start(Stage primaryStage) {
        ObservableList<String> allItems = FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five");
        ComboBox<String> combo = new ComboBox<>(allItems);

        combo.setCellFactory(lv -> new ListCell<String>() {

            {
                disableProperty().bind(combo.valueProperty().isEqualTo(itemProperty()));
            }

            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                setText(item);
            }
        });

        BorderPane root = new BorderPane();
        root.setTop(combo);
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

【讨论】:

  • 好的,但由于某些原因,前两个或三个更改甚至删除了其他元素.. 一段时间后它工作得很好,但我最终从列表中丢失了两个或三个项目
  • FilteredList items = classi.filtered(item -> item != class1.getValue()); class1.setItems(项目); class1.valueProperty().addListener((obs, oldValue, newValue) -> Platform.runLater(() -> items.setPredicate(item -> item != newValue)));
猜你喜欢
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
  • 2018-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多