设置监听器Combobox JavaFX

时间:2017-05-25 20:46:04

标签: java javafx combobox interface listener

嗨,我有一些组合框的问题。我有一个带有四个组合框的界面,它们使用相同列表的项目。我在其中一个组合框中添加了一个监听器,我想在我选择一个项目时完成监听器而不是在列表更改时完成,但是当我从列表中删除一个项目时,使用这个监听器,automaticalli再次运行

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

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

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

            });

所以最后他每次执行删除时都会运行此侦听器,并最终以错误结束

1 个答案:

答案 0 :(得分:0)

问题基本上出现是因为您正在处理该列表中的更改时最终更改可观察列表(选择模型' s 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);
    }
}