JavaFX可搜索的组合框(如js select2) [英] JavaFX searchable combobox (like js select2)

查看:109
本文介绍了JavaFX可搜索的组合框(如js select2)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为javafx寻找像select2这样的组件。

I am looking for a component like select2 for javafx.

一个组合框,当弹出窗口显示并在下面过滤listview时,它将有一个可搜索的文本字段。

A combobox which will have a searchable textfield when the popup appears and filtered listview below.

任何想法或事情已经完成了吗?

Any ideas or something that is done already?

推荐答案

我自己实现了这个几个月前。这个想法基本上是你将 ComboBox 下拉列表包装在 FilteredList 中,然后添加一个监听器 ComboBox #textProperty()更改 FilteredList 的谓词。

I implemented this myself a couple of months ago. The idea is basically that you wrap the ComboBox drop-down list in a FilteredList, and then you add a listener to the ComboBox#textProperty() that changes the predicate for the FilteredList.

我的类包含许多额外的功能,例如将小写输入转换为大写并限制输入长度的选项。如果你不需要它们,你可以删除它们。

My class contains a lot of extra functionality such as the option to transform lower case input to upper case and restricting the length of the input. You can just remove those parts if you don't need them.

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
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 MCVE extends Application {

    @Override
    public void start(Stage stage) {
        ComboBox<String> box = new ComboBox<String>();
        box.setEditable(true);

        // For the combo box filter to work properly we need to create the item
        // list and wrap it in a FilteredList.
        ObservableList<String> items = FXCollections.observableArrayList("One", "Two", "Three", "OneTwo", "ThreeTwo",
                "OneTwoThree");
        FilteredList<String> filteredItems = new FilteredList<String>(items);

        // Then you need to provide the InputFilter with the FilteredList in the
        // constructor call.
        box.getEditor().textProperty().addListener(new InputFilter(box, filteredItems, false));

        box.setItems(filteredItems);

        BorderPane view = new BorderPane();
        view.setCenter(box);

        stage.setScene(new Scene(view));
        stage.show();
    }

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

    /**
     * 
     * @author Jonatan Stenbacka
     *
     */
    class InputFilter implements ChangeListener<String> {

        private ComboBox<String> box;
        private FilteredList<String> items;
        private boolean upperCase;
        private int maxLength;
        private String restriction;

        /**
         * @param box
         *            The combo box to whose textProperty this listener is
         *            added.
         * @param items
         *            The {@link FilteredList} containing the items in the list.
         */
        public InputFilter(ComboBox<String> box, FilteredList<String> items, boolean upperCase, int maxLength,
                String restriction) {
            this.box = box;
            this.items = items;
            this.upperCase = upperCase;
            this.maxLength = maxLength;
            this.restriction = restriction;
        }

        public InputFilter(ComboBox<String> box, FilteredList<String> items, boolean upperCase, int maxLength) {
            this(box, items, upperCase, maxLength, null);
        }

        public InputFilter(ComboBox<String> box, FilteredList<String> items, boolean upperCase) {
            this(box, items, upperCase, -1, null);
        }

        public InputFilter(ComboBox<String> box, FilteredList<String> items) {
            this(box, items, false);
        }

        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
            StringProperty value = new SimpleStringProperty(newValue);

            // If any item is selected we save that reference.
            String selected = box.getSelectionModel().getSelectedItem() != null
                    ? box.getSelectionModel().getSelectedItem() : null;

            String selectedString = null;
            // We save the String of the selected item.
            if (selected != null) {
                selectedString = (String) selected;
            }

            if (upperCase) {
                value.set(value.get().toUpperCase());
            }

            if (maxLength >= 0 && value.get().length() > maxLength) {
                value.set(oldValue);
            }

            if (restriction != null) {
                if (!value.get().matches(restriction + "*")) {
                    value.set(oldValue);
                }
            }

            // If an item is selected and the value in the editor is the same
            // as the selected item we don't filter the list.
            if (selected != null && value.get().equals(selectedString)) {
                // This will place the caret at the end of the string when
                // something is selected.
                Platform.runLater(() -> box.getEditor().end());
            } else {
                items.setPredicate(item -> {
                    String itemString = item;
                    if (itemString.toUpperCase().contains(value.get().toUpperCase())) {
                        return true;
                    } else {
                        return false;
                    }
                });
            }

            // If the popup isn't already showing we show it.
            if (!box.isShowing()) {
                // If the new value is empty we don't want to show the popup,
                // since
                // this will happen when the combo box gets manually reset.
                if (!newValue.isEmpty() && box.isFocused()) {
                    box.show();
                }
            }
            // If it is showing and there's only one item in the popup, which is
            // an
            // exact match to the text, we hide the dropdown.
            else {
                if (items.size() == 1) {
                    // We need to get the String differently depending on the
                    // nature
                    // of the object.
                    String item = items.get(0);

                    // To get the value we want to compare with the written
                    // value, we need to crop the value according to the current
                    // selectionCrop.
                    String comparableItem = item;

                    if (value.get().equals(comparableItem)) {
                        Platform.runLater(() -> box.hide());
                    }
                }
            }

            box.getEditor().setText(value.get());
        }
    }
}

这篇关于JavaFX可搜索的组合框(如js select2)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆