简体   繁体   English

GlazedList:使用set方法更新表中显示的事件列表可删除表选择

[英]GlazedList: using the set method to update eventlist displayed in table removes table selection

I am using GlazedList with JFX TableView. 我在JFX TableView中使用GlazedList。

I have the following code: 我有以下代码:

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);
}

Problem: When selecting multiple rows in the table, and the method updatePerson is called, after "person_list.set(index, person);" 问题:在表中选择多行时,在“ person_list.set(index,person);”之后调用updatePerson方法。 is called, all my table selection except for the last selected row are un-selected. 称为时,除最后选择的行外,我所有的表选择都未被选择。

When is "updatePerson" called? 什么时候调用“ updatePerson”? This method is called every time my back-end receives an update and push this updated value to my front-end. 每当我的后端收到更新并将此更新的值推送到我的前端时,都会调用此方法。 It happens periodically every few seconds. 它每隔几秒钟定期发生一次。

What i wish to achieve: When user selects multiple row, the table will continue to reflect the updated values without deselecting my selected rows. 我希望实现的目标:当用户选择多行时,该表将继续反映更新后的值,而无需取消选择我选择的行。

EDIT: The following is a sample code i used to test. 编辑:以下是我用来测试的示例代码。

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;
        }
    }
}

Try using shift click to select multiple row, then click on the edit button, the 3rd row will be updated but all multiple selected rows will be unselected, except for one row. 尝试使用shift单击选择多行,然后单击“编辑”按钮,第3行将被更新,但除一行以外,所有选中的所有行都将被取消选择。

I think you would benefit from looking at my answer to a similar question: GlazedList update EventList in JTable 我认为您可以从我对类似问题的回答中受益: GlazedList更新JTable中的EventList

You should be able to update the items in the collection without having to get & set on the list itself. 你应该能够更新集合中的项目,而无需getset列表本身上。

Also, make sure you're using the proper event selection model to obtain the selected items. 另外,请确保使用正确的事件选择模型来获取所选项目。 Then you won't need to maintain the map object. 然后,您将不需要维护map对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM