应用表格过滤器

时间:2015-04-14 21:27:06

标签: javafx-8

我有这个Java表的例子,它每秒生成一次值。

简短的例子:

MainApp.java

public class MainApp extends Application
{    
    private TableView<Employee> table;
    private TextField txtField;
    private ObservableList<Employee> data;

    MyService myService;

    @Override
    public void start(Stage stage) throws Exception
    {
        Label lbl = new Label("Enter text below to filter: ");
        initFilter();
        initTable();

        myService = new MyService();

        myService.setDelay(new Duration(300));
        myService.setPeriod(new Duration(1000));

        myService.start();

        VBox container = new VBox();
        container.getChildren().addAll(lbl, txtField, table);
        StackPane root = new StackPane();
        root.getChildren().add(container);
        Scene scene = new Scene(root, 500, 400);
        stage.setScene(scene);
        stage.show();
    }

    class MyService extends ScheduledService<Void>
    {    
        @Override
        protected Task<Void> createTask()
        {
            return new Task<Void>()
            {
                @Override
                protected Void call() throws Exception
                {
                    data = getTableData();
                    table.setItems(FXCollections.observableArrayList(data));
                    return null;
                }
            };
        }
    }

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

    private void initTable()
    {
        table = new TableView<>();
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        TableColumn<Employee, String> empIdCol = new TableColumn<>("Employee ID");
        empIdCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Employee, String>, ObservableValue<String>>()
        {

            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<Employee, String> p)
            {
                return p.getValue().empIdProperty();
            }
        });

        TableColumn<Employee, String> nameCol = new TableColumn<>("Name");
        nameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Employee, String>, ObservableValue<String>>()
        {

            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<Employee, String> p)
            {
                return p.getValue().nameProperty();
            }
        });

        TableColumn<Employee, Number> ageCol = new TableColumn<>("Age");
        ageCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Employee, Number>, ObservableValue<Number>>()
        {

            @Override
            public ObservableValue<Number> call(TableColumn.CellDataFeatures<Employee, Number> p)
            {
                return p.getValue().ageProperty();
            }
        });

        TableColumn<Employee, String> cityCol = new TableColumn<>("City");
        cityCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Employee, String>, ObservableValue<String>>()
        {

            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<Employee, String> p)
            {
                return p.getValue().cityProperty();
            }
        });

        table.getColumns().setAll(empIdCol, nameCol, ageCol, cityCol);

    }

    private void initFilter()
    {
        txtField = new TextField();
        txtField.setPromptText("Filter");
        txtField.textProperty().addListener(new InvalidationListener()
        {
            @Override
            public void invalidated(Observable o)
            {
                if (txtField.textProperty().get().isEmpty())
                {
                    table.setItems(data);
                    return;
                }
                ObservableList<Employee> tableItems = FXCollections.observableArrayList();
                ObservableList<TableColumn<Employee, ?>> cols = table.getColumns();
                for (int i = 0; i < data.size(); i++)
                {

                    for (int j = 0; j < cols.size(); j++)
                    {
                        TableColumn col = cols.get(j);
                        String cellValue = col.getCellData(data.get(i)).toString();
                        cellValue = cellValue.toLowerCase();
                        if (cellValue.contains(txtField.textProperty().get().toLowerCase()))
                        {
                            tableItems.add(data.get(i));
                            break;
                        }
                    }

                }
                table.setItems(tableItems);
            }
        });
    }

    private ObservableList<Employee> getTableData()
    {
        ObservableList<Employee> list = FXCollections.observableArrayList();
        String[] name =
        {
            "Sriram", "Pete", "Eric", "Dawson", "John"
        };
        String[] city =
        {
            "New York", "Chicago", "Little Rock", "Los Angeles", "Oakland"
        };
        for (int i = 0; i < 5; i++)
        {
            Employee emp = new Employee();
            emp.setName(name[i]);
            emp.setAge((int) (Math.random() * 100));
            emp.setCity(city[i]);
            emp.setEmpId(String.valueOf(i + 1000));
            list.add(emp);
        }
        return list;
    }

}

Employee.java

 public class Employee {

        private SimpleStringProperty name = new SimpleStringProperty();
        private SimpleIntegerProperty age = new SimpleIntegerProperty();
        private SimpleStringProperty city = new SimpleStringProperty();
        private SimpleStringProperty empId = new SimpleStringProperty();

        public SimpleStringProperty nameProperty() {
            return name;
        }

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

        public String getName() {
            return name.get();
        }

        public SimpleIntegerProperty ageProperty() {
            return age;
        }

        public void setAge(Integer age) {
            this.age.set(age);
        }

        p

ublic Integer getAge() {
        return age.get();
    }

    public SimpleStringProperty cityProperty() {
        return city;
    }

    public String getCity() {
        return city.get();
    }

    public void setCity(String city) {
        this.city.set(city);
    }

    public SimpleStringProperty empIdProperty() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId.set(empId);
    }

    public String getEmpId() {
        return empId.get();
    }
    }

我注意到我用来过滤内容的过滤器仅适用于当前的Service运行。 对于下一次运行,不应用过滤器。

1 个答案:

答案 0 :(得分:1)

使用FilteredList管理过滤。不是直接更新列表,而是从服务中替换其源列表的内容。当文本字段中的文本发生更改时,只需更新已过滤列表的谓词。

另外,您的代码会从后台线程更新TableView,这违反了JavaFX的线程规则。这在以下示例中已得到修复。

SSCCE:

import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class FilteredTableViewExample extends Application {
    private TableView<Employee> table;
    private TextField txtField;
    private FilteredList<Employee> tableData;
    private ObservableList<Employee> data;

    MyService myService;

    @Override
    public void start(Stage stage) throws Exception {
        Label lbl = new Label("Enter text below to filter: ");
        initFilter();
        initTable();

        myService = new MyService();

        myService.setDelay(new Duration(300));
        myService.setPeriod(new Duration(1000));

        myService.start();

        VBox container = new VBox();
        container.getChildren().addAll(lbl, txtField, table);
        StackPane root = new StackPane();
        root.getChildren().add(container);
        Scene scene = new Scene(root, 500, 400);
        stage.setScene(scene);
        stage.show();
    }

    class MyService extends ScheduledService<List<Employee>> {
        @Override
        protected Task<List<Employee>> createTask() {
            Task<List<Employee>> task = new Task<List<Employee>>() {
                @Override
                protected List<Employee> call() throws Exception {
                    return getTableData();
                }
            };
            task.setOnSucceeded(e -> data.setAll(task.getValue()));
            return task ;
        }
    }

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

    private void initTable() {
        table = new TableView<>();
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        TableColumn<Employee, String> empIdCol = new TableColumn<>("Employee ID");
        empIdCol.setCellValueFactory(p -> p.getValue().empIdProperty());

        TableColumn<Employee, String> nameCol = new TableColumn<>("Name");
        nameCol.setCellValueFactory(p -> p.getValue().nameProperty());

        TableColumn<Employee, Number> ageCol = new TableColumn<>("Age");
        ageCol.setCellValueFactory(p -> p.getValue().ageProperty());

        TableColumn<Employee, String> cityCol = new TableColumn<>("City");
        cityCol.setCellValueFactory(p -> p.getValue().cityProperty());

        table.getColumns().setAll(empIdCol, nameCol, ageCol, cityCol);

        data = FXCollections.observableArrayList();
        tableData = new FilteredList<>(data);
        table.setItems(tableData);
    }

    private void initFilter() {
        txtField = new TextField();
        txtField.setPromptText("Filter");
        txtField.textProperty().addListener((obs, oldText, newText) -> {
            if (txtField.textProperty().get().isEmpty()) {
                tableData.setPredicate(employee -> true);
                return;
            }

            tableData.setPredicate(employee -> {
                String text = newText.toLowerCase();
                for (TableColumn<Employee, ?> col : table.getColumns()) {
                    String cellValue = col.getCellData(employee).toString();
                    cellValue = cellValue.toLowerCase();
                    if (cellValue.contains(text)) {
                        return true;
                    }
                }
                return false;
            });

        });
    }

    private List<Employee> getTableData() {
        List<Employee> list = new ArrayList<>();
        String[] name = { "Sriram", "Pete", "Eric", "Dawson", "John" };
        String[] city = { "New York", "Chicago", "Little Rock", "Los Angeles", "Oakland" };
        for (int i = 0; i < 5; i++) {
            Employee emp = new Employee();
            emp.setName(name[i]);
            emp.setAge((int) (Math.random() * 100));
            emp.setCity(city[i]);
            emp.setEmpId(String.valueOf(i + 1000));
            list.add(emp);
        }
        return list;
    }

    public static class Employee {

        private SimpleStringProperty name = new SimpleStringProperty();
        private SimpleIntegerProperty age = new SimpleIntegerProperty();
        private SimpleStringProperty city = new SimpleStringProperty();
        private SimpleStringProperty empId = new SimpleStringProperty();

        public SimpleStringProperty nameProperty() {
            return name;
        }

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

        public String getName() {
            return name.get();
        }

        public SimpleIntegerProperty ageProperty() {
            return age;
        }

        public void setAge(Integer age) {
            this.age.set(age);
        }

        public Integer getAge() {
            return age.get();
        }

        public SimpleStringProperty cityProperty() {
            return city;
        }

        public String getCity() {
            return city.get();
        }

        public void setCity(String city) {
            this.city.set(city);
        }

        public SimpleStringProperty empIdProperty() {
            return empId;
        }

        public void setEmpId(String empId) {
            this.empId.set(empId);
        }

        public String getEmpId() {
            return empId.get();
        }
    }
}