第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

更改 ComboBox 的項目而不更改 ValueProperty

更改 ComboBox 的項目而不更改 ValueProperty

尚方寶劍之說 2021-12-30 20:41:16
編輯:我試圖構(gòu)建一個帶有搜索功能的組合框,這就是我想出的:public class SearchableComboBox<T> extends ComboBox<T> {private ObservableList<T> filteredItems;private ObservableList<T> originalItems;private T selectedItem;private StringProperty filter = new SimpleStringProperty("");public SearchableComboBox () {    this.setTooltip(new Tooltip());    this.setOnKeyPressed(this::handleOnKeyPressed);    this.getTooltip().textProperty().bind(filter);    this.showingProperty().addListener(new ChangeListener<Boolean>() {        @Override        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {            // If user "closes" the ComboBox dropdown list: reset filter, reset list to the full original list, hide tooltip            if (newValue == false) {                filter.setValue("");;                setItems(originalItems);                getTooltip().hide();            // If user opens the combobox dropdown list: get a copy of the items and show tooltip               } else {                originalItems = getItems();                Window stage = getScene().getWindow();                getTooltip().show(stage);            }        }    });}public void handleOnKeyPressed(KeyEvent e) {    //Only execute if the dropdown list of the combobox is opened    if (this.showingProperty().getValue() == true) {        // Get key and add it to the filter string        String c = e.getText();        filter.setValue(filter.getValue() + c);        //Filter out objects that dont contain the filter        this.filteredItems = this.originalItems.filtered(a -> this.getConverter().toString(a).toLowerCase().contains(filter.getValue().toLowerCase()));        //Set the items of the combox to the filtered list        this.setItems(filteredItems);    }}這個想法很簡單:只要打開組合框的下拉列表,我就會監(jiān)聽按鍵并將字符添加到過濾器中。使用這些過濾器,組合框的項目列表被過濾為僅包含包含過濾字符串的項目的列表。然后我使用 setItems 將項目列表設(shè)置為我的過濾列表。我的問題是,組合框的 valueProperty 更改,但我希望所選對象保持不變,直到用戶從下拉列表中選擇另一個。
查看完整描述

2 回答

?
白板的微信

TA貢獻1883條經(jīng)驗 獲得超3個贊

我的建議是FilteredList從您的原始列表中創(chuàng)建一個。然后,使用 aPredicate過濾掉不匹配的結(jié)果。如果您將ComboBox項目設(shè)置為該過濾列表,它將始終顯示所有項目或與您的搜索詞匹配的項目。


將ValueProperty只會更新,當用戶“提交”按變化[進入]。


我在這里有一個簡短的 MCVE 應(yīng)用程序來演示整個注釋:


import javafx.application.Application;

import javafx.collections.FXCollections;

import javafx.collections.ObservableList;

import javafx.collections.transformation.FilteredList;

import javafx.geometry.Insets;

import javafx.geometry.Pos;

import javafx.scene.Scene;

import javafx.scene.control.ComboBox;

import javafx.scene.layout.VBox;

import javafx.stage.Stage;


public class Main extends Application {


    // Create a list of items

    private final ObservableList<String> items = FXCollections.observableArrayList();


    // Create the ComboBox

    private final ComboBox<String> comboBox = new ComboBox<>();


    public static void main(String[] args) {

        launch(args);

    }


    @Override

    public void start(Stage primaryStage) {


        // Simple Interface

        VBox root = new VBox(10);

        root.setAlignment(Pos.CENTER);

        root.setPadding(new Insets(10));


        // Allow manual entry into ComboBox

        comboBox.setEditable(true);


        // Add sample items to our list

        items.addAll("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten");


        createListener();


        root.getChildren().add(comboBox);


        // Show the stage

        primaryStage.setScene(new Scene(root));

        primaryStage.setTitle("Filtered ComboBox");

        primaryStage.show();

    }


    private void createListener() {


        // Create the listener to filter the list as user enters search terms

        FilteredList<String> filteredList = new FilteredList<>(items);


        // Add listener to our ComboBox textfield to filter the list

        comboBox.getEditor().textProperty().addListener((observable, oldValue, newValue) ->

                filteredList.setPredicate(item -> {


                    // If the TextField is empty, return all items in the original list

                    if (newValue == null || newValue.isEmpty()) {

                        return true;

                    }


                    // Check if the search term is contained anywhere in our list

                    if (item.toLowerCase().contains(newValue.toLowerCase().trim())) {

                        return true;

                    }


                    // No matches found

                    return false;

                }));


        // Finally, let's add the filtered list to our ComboBox

        comboBox.setItems(filteredList);


    }

}

您將擁有一個簡單的、可編輯的 ComboBox,它可以從列表中過濾掉不匹配的值。


使用這種方法,您不需要監(jiān)聽每個按鍵,但可以在其Predicate自身內(nèi)提供任何過濾指令,如上所示。


結(jié)果:

http://img1.sycdn.imooc.com//61cda9160001c01803190390.jpghttp://img1.sycdn.imooc.com//61cda91c00016b1203190212.jpg

編輯:


ComboBox但是,可編輯項存在一些問題需要解決,因為從列表中選擇一個項目會引發(fā)IndexOutOfBoundsException.


這可以通過使用單獨TextField的過濾器來緩解,但保持與上述基本相同的代碼。而不是將偵聽器添加到comboBox.getEditor(),只需將其更改為textField。這將毫無問題地過濾列表。


這是使用該方法的完整 MCVE:


import javafx.application.Application;

import javafx.collections.FXCollections;

import javafx.collections.ObservableList;

import javafx.collections.transformation.FilteredList;

import javafx.geometry.Insets;

import javafx.geometry.Pos;

import javafx.scene.Scene;

import javafx.scene.control.ComboBox;

import javafx.scene.control.TextField;

import javafx.scene.layout.VBox;

import javafx.stage.Stage;


public class Main extends Application {


    // Create a list of items

    private final ObservableList<String> items = FXCollections.observableArrayList();


    // Create the search field

    TextField textField = new TextField("Filter ...");


    // Create the ComboBox

    private final ComboBox<String> comboBox = new ComboBox<>();


    public static void main(String[] args) {

        launch(args);

    }


    @Override

    public void start(Stage primaryStage) {


        // Simple Interface

        VBox root = new VBox(10);

        root.setAlignment(Pos.CENTER);

        root.setPadding(new Insets(10));


        // Add sample items to our list

        items.addAll("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten");


        createListener();


        root.getChildren().addAll(textField, comboBox);


        // Show the stage

        primaryStage.setScene(new Scene(root));

        primaryStage.setTitle("Filtered ComboBox");

        primaryStage.show();

    }


    private void createListener() {


        // Create the listener to filter the list as user enters search terms

        FilteredList<String> filteredList = new FilteredList<>(items);


        // Add listener to our ComboBox textfield to filter the list

        textField.textProperty().addListener((observable, oldValue, newValue) ->

                filteredList.setPredicate(item -> {


                    // If the TextField is empty, return all items in the original list

                    if (newValue == null || newValue.isEmpty()) {

                        return true;

                    }


                    // Check if the search term is contained anywhere in our list

                    if (item.toLowerCase().contains(newValue.toLowerCase().trim())) {

                        return true;

                    }


                    // No matches found

                    return false;

                }));


        // Finally, let's add the filtered list to our ComboBox

        comboBox.setItems(filteredList);


        // Allow the ComboBox to extend in size

        comboBox.setMaxWidth(Double.MAX_VALUE);


    }

}

http://img1.sycdn.imooc.com//61cda93100017d6302270199.jpg

查看完整回答
反對 回復 2021-12-30
?
森欄

TA貢獻1810條經(jīng)驗 獲得超5個贊

我發(fā)現(xiàn)的最佳解決方案是稍微修改的版本:JavaFX searchable combobox (like js select2)


我修改的內(nèi)容是使 InputFilter 類通用,并且組合框在關(guān)閉下拉列表后失去焦點。這里的代碼:


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.transformation.FilteredList;

import javafx.scene.control.ComboBox;


public class InputFilter<T> implements ChangeListener<String> {


private ComboBox<T> box;

private FilteredList<T> items;

private boolean upperCase;

private int maxLength;

private String restriction;

private int count = 0;


/**

 * @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<T> box, FilteredList<T> items, boolean upperCase, int maxLength,

        String restriction) {

    this.box = box;

    this.items = items;

    this.upperCase = upperCase;

    this.maxLength = maxLength;

    this.restriction = restriction;

    this.box.setItems(items);

    this.box.showingProperty().addListener(new ChangeListener<Boolean>() {


        @Override

        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {

            if (newValue == false) {

                items.setPredicate(null);

                box.getParent().requestFocus();

            }


        }


    });

}


public InputFilter(ComboBox<T> box, FilteredList<T> items, boolean upperCase, int maxLength) {

    this(box, items, upperCase, maxLength, null);

}


public InputFilter(ComboBox<T> box, FilteredList<T> items, boolean upperCase) {

    this(box, items, upperCase, -1, null);

}


public InputFilter(ComboBox<T> box, FilteredList<T> items) {

    this(box, items, false);

}


@Override

public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {

    StringProperty value = new SimpleStringProperty(newValue);

    this.count++;

    System.out.println(this.count);

    System.out.println(oldValue);

    System.out.println(newValue);

    // If any item is selected we save that reference.

    T selected = box.getSelectionModel().getSelectedItem() != null

            ? box.getSelectionModel().getSelectedItem() : null;


    String selectedString = null;

    // We save the String of the selected item.

    if (selected != null) {

        selectedString =  this.box.getConverter().toString(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.

        System.out.println(value.get());

        System.out.println(selectedString);

        Platform.runLater(() -> box.getEditor().end());

    } else {

        items.setPredicate(item -> {

            System.out.println("setPredicate");

            System.out.println(value.get());

            T itemString = item;

            if (this.box.getConverter().toString(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.

            T 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.

            T comparableItem = item;


            if (value.get().equals(comparableItem)) {

                Platform.runLater(() -> box.hide());

            }

        }

    }


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

}

}


然后將 InputFilter 添加為 Combobox 的 textField 的更改偵聽器:


comboBox.getEditor().textProperty().addListener(new InputFilter<YourCustomClass>(comboBox, new FilteredList<YourCustomClass>(comboBox.getItems())));

目前Combobox.setEditable(true)必須在外部手動完成,但我計劃將其移入 InputFilter 本身。您還需要為 Combobox 設(shè)置一個字符串轉(zhuǎn)換器。到目前為止,這個解決方案對我來說很糟糕,唯一缺少的是在輸入搜索鍵時支持空格鍵。


查看完整回答
反對 回復 2021-12-30
  • 2 回答
  • 0 關(guān)注
  • 141 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號