JavaFX利用ListView做一个带搜索功能的多选框

        之前考虑过使用ComboBox做一个带搜索功能的多选下拉列表,但是发现实现过程中有些小坑,使用过其他大佬的案例,但是最终都存在一些小问题,没法实现自己想要的效果。后来在B站Aimls大神的视频中得到启发,使用TextField来完成搜索功能,这样做起来可以更轻松的实现搜索和多选。

        设计思路是TextField作为一个接收搜索字符的入口,在输入关键词后ListView检索出相关内容,并刷新数据源。ListView设置为单选模式,点击每一项都会让数据变成选中。

        直接上一段写好的代码吧,本人菜鸟,也没有过多的测试,有问题欢迎各位大佬指出。

package sample;

import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxListCell;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;

import java.util.function.Consumer;
import java.util.function.Predicate;

public class Main extends Application {

    ObservableList<Data> items = FXCollections.observableArrayList();
    ObservableList<Data> tmpList = FXCollections.observableArrayList();

    @Override
    public void start(Stage primaryStage) throws Exception{

        HBox hb = new HBox(20);
        VBox root = new VBox(1);
        ListView<Data> listView = new ListView<Data>();
        ObservableList<Data> list = FXCollections.observableArrayList();

        Button selectFull = new Button("全选");
        Button clearBtn = new Button("清除");
        hb.getChildren().addAll(selectFull,clearBtn);
        TextField tf = new TextField();

        Data data1 = new Data("item1");
        Data data2 = new Data("item2",true);
        Data data3 = new Data("item3");
        Data data4 = new Data("item4");
        list.addAll(data1,data2,data3,data4);

        tf.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                System.out.println("搜索:"+newValue);
                tmpList = items.filtered(new Predicate<Data>() {
                    @Override
                    public boolean test(Data data) {
                        return data.getName().contains(newValue);
                    }
                });
                listView.setItems(tmpList);
            }
        });

        listView.setItems(list);

        tmpList = listView.getItems();
        items = listView.getItems();

        Callback<ListView<Data>,ListCell<Data>> call = CheckBoxListCell.forListView(new Callback<Data, ObservableValue<Boolean>>() {
            @Override
            public ObservableValue<Boolean> call(Data param) {
                if (param.isIsSelected()){
                    return param.isSelectedProperty();
                }
                param.setIsSelected(false);
                return param.isSelectedProperty();
            }
        }, new StringConverter<Data>() {
            @Override
            public String toString(Data object) {
                return object.getName();
            }

            @Override
            public Data fromString(String string) {
                return new Data(string);
            }
        });

        listView.setCellFactory(call);

        listView.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if (listView.getSelectionModel().getSelectedItem() != null){
                    listView.getSelectionModel().getSelectedItem().setIsSelected(!listView.getSelectionModel().getSelectedItem().isIsSelected());
                }
            }
        });

        listView.getItems().forEach(new Consumer<Data>() {
            @Override
            public void accept(Data data) {
                data.isSelectedProperty().addListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        System.out.println("data:"+data.getName()+":"+newValue);
                    }
                });
            }
        });

        selectFull.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                tmpList.forEach(new Consumer<Data>() {
                    @Override
                    public void accept(Data data) {
                        data.setIsSelected(true);
                    }
                });
            }
        });

        clearBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                tmpList.forEach(new Consumer<Data>() {
                    @Override
                    public void accept(Data data) {
                        data.setIsSelected(false);
                    }
                });
            }
        });

        root.getChildren().addAll(tf,hb,listView);

        primaryStage.setTitle("带搜索的多选");
        primaryStage.setScene(new Scene(root, 250, 250));
        primaryStage.show();
    }


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

class Data{
    private String name;
    private SimpleBooleanProperty isSelected = new SimpleBooleanProperty();

    public Data(String name, Boolean isSelected) {
        this.name = name;
        this.isSelected = new SimpleBooleanProperty(isSelected);
    }

    public Data(String name){
        this.name = name;
        this.isSelected = new SimpleBooleanProperty(false);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isIsSelected() {
        return isSelected.get();
    }

    public SimpleBooleanProperty isSelectedProperty() {
        return isSelected;
    }

    public void setIsSelected(boolean isSelected) {
        this.isSelected.set(isSelected);
    }
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 JavaFX 表格界面示例: ```java import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class TableDemo extends Application { @Override public void start(Stage primaryStage) throws Exception { // 创建表格 GridPane gridPane = new GridPane(); gridPane.setHgap(10); gridPane.setVgap(10); // 添加表格内容 for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { Pane pane = new StackPane(); Label label = new Label(String.format("(%d, %d)", i, j)); pane.getChildren().addAll(new Rectangle(50, 50, Color.WHITE), label); pane.setStyle("-fx-border-color: black"); gridPane.add(pane, i, j); } } // 创建布局 BorderPane root = new BorderPane(); root.setCenter(gridPane); root.setPadding(new Insets(10, 10, 10, 10)); // 创建场景 Scene scene = new Scene(root, 400, 300); // 设置场景 primaryStage.setScene(scene); primaryStage.setTitle("Table Demo"); primaryStage.show(); } public static void main(String[] args) { launch(args); } } ``` 这个示例使用了 GridPane、StackPane、Rectangle 和 Label 这些 JavaFX 控件来创建一个简单的有边框的表格界面。您可以根据自己的需要调整表格的大小、边框颜色等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值