首页 > 解决方案 > GlazedList:使用set方法更新表中显示的事件列表删除表选择

问题描述

我将 GlazedList 与 JFX TableView 一起使用。

我有以下代码:

TableView<Person> table = new TableView<Person>();
table.getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE );
EventList<Person> person_list = new BasicEventList<Person>();
Map<int, Person> map;

public void updatePerson(Person p){
  int personID = p.getID();
  int index = person_list.indexOf( map.get(personID) );

  Person person = person_list.get(index);
  person.setFirstName(p.getFirstName());
  person.setLastName(p.getLastName());

  person_list.set(index, person);
}

问题:在表中选择多个行并在“ person_list.set(index,person)”之后调用方法更新时;被调用,我所有的表选择除了最后选择的行都未选择。

何时调用“updatePerson”?每次我的后端收到更新并将这个更新的值推送到我的前端时,都会调用此方法。它每隔几秒钟周期性地发生一次。

我希望实现的目标:当用户选择多行时,表格将继续反映更新的值,而不会取消选择我选择的行。

编辑:以下是我用来测试的示例代码。

public class ObservableJFXTableView extends Application {
    private final TableView<Person> table = new TableView<>();
    private FilterMatcherEditor filterMatcherEditor = new FilterMatcherEditor();

    private EventList<Person> people;
    private ObservableList<Person> data;
    final HBox hb = new HBox();

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

    private void setupGlazedList(){
        people = new BasicEventList<Person>();

        ObservableElementList.Connector<Person> personCOnnector = GlazedLists.beanConnector(Person.class);
        EventList<Person> observedPeople = new ObservableElementList<Person>(people, personConnector);

        EventList<Person> filtered_list = new FilterList<Person(observedPeople, filterMatcherEditor);
        data = new EventObservableList<Person>(filtered_list);
    }

    private void populatedList(){
        people.add(new Person("Jacob", "Smith", "a@example.com"));
        people.add(new Person("James", "Johnson", "b@example.com"));
        people.add(new Person("Christopher", "Lim", "c@example.com"));
        people.add(new Person("Emma", "Jones", "d@example.com"));
        people.add(new Person("Michael", "Brown", "a@example.com"));
    }

    @Override
    public void start(Stage stage){
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Example");
        stage.setWidth(450);
        stage.setHeight(550);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial"), 20);

        table.setEditable(true);
        table.getSelectionModel().setSeletionMode(SelectionMode.MULTIPLE);

        TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));

        TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));

        TableColumn<Person, String> emailCol = new TableColumn<>("Email");
        emailCol.setMinWidth(100);
        emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));

        setupGlazedList();
        populatedList();

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);

        final Button editButton = new Button("Edit -> people.get(2)");
        editButton.setOnAction((ActionEvent e) -> {
            people.get(2).setFirstName("NewFirst");
            people.get(2).setLastName("NewLast");
            people.get(2).setEmail("NewEmail");
        });

        hb.getChildren().add(editButton);
        hb.setSpacing(3);

        final VBox vbox = new VBox();
        vbox.setSpaceing(5);
        vbox.setPadding(new Insets(10,0,0,10));
        vbox.getChildren().addAll(filterMatcherEditor.getTextField(), label, table, hb);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();
    }

    private static class FilterMatcherEditor extends AbstractMatcherEditor<Person>{
        private TextField tf;

        public FilterMatcherEditor(){
            tf = new TextField();
            tf.textProperty().addListener((observable, oldValue, newValue) -> filterChanged());
        }

        public TextField getTextField(){
            return tf;
        }

        public void filterChanged(){
            if (tf.getText().isEmpty())
                this.fireMatchAll();
            else
                this.fireChanged(new FilterMatcher(tf.getText()));
        }

        private static class FilterMatcher implements Matcher {
            private final String textFieldInput;

            public FilterMatcher(String text){
                this.textFieldInput = text;
            }

            public boolean matched(Object obj){
                final Person person = (Person) obj;

                for (Object obj: person.getAll()){
                    String str = ((String) obj).toUpperCase();
                    if ( str.contains(textFieldInput.toUpperCase()))
                        return true;
                }
                return false;
            }
        }
    }

    public class Person {
        private final SimpleStringProperty firstName;
        private final SimpleStringProeprty lastName;
        private final SimpleStringProperty email;

        private final PropertyChangeSupport support = new PropertyChangeSupport(this);

        private Person(String fName, String lName, String email){
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public void addPropertyChangeListener(PropertyChangeListener l){
            support.addPropertyChangeListener(l);
        }
        public void removePropertyChangeListener(PropertyChangeListener l){
            support.removePropertyChangeListener(l);
        }

        public String getFirstName(){
            return firstName.get();
        }
        public void setFirstName(String str){
            final String old = firstName.get();
            firstName.set(str);
            support.firePropertyCHange("firstName", old, str);
        }

        public String getLastName(){
            return lastName.get();
        }
        public void setLastName(String str){
            final String old = lastName.get();
            lastName.set(str);
            support.firePropertyCHange("lastName", old, str);
        }

        public String getEmail(){
            return email.get();
        }
        public void setEmail(String str){
            final String old = email.get();
            email.set(str);
            support.firePropertyCHange("email", old, str);
        }

        public List<String> getAll(){
            List<String> strList = new ArrayList<String>();
            strList.add(firstName.get());
            strList.add(lastName.get());
            strList.add(email.get());

            return strList;
        }
    }
}

尝试使用 shift click 选择多行,然后单击编辑按钮,第三行将被更新,但所有多行选定的行都将被取消选择,除了一行。

标签: javaselectionglazedlists

解决方案


我认为您会从我对类似问题的回答中受益:GlazedList update EventList in JTable

您应该能够更新集合中的项目,而不必在列表本身上get& 。set

此外,请确保您使用正确的事件选择模型来获取所选项目。然后你就不需要维护map对象了。


推荐阅读