GlazedList: использование метода set для обновления списка событий, отображаемого в таблице, убирает выбор таблицы - PullRequest
0 голосов
/ 27 июня 2018

Я использую 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);
}

Проблема: При выборе нескольких строк в таблице и вызывается метод updatePerson, после «person_list.set (index, person);» вызывается, все мои выбор таблицы, кроме последней выбранной строки, не выбраны.

Когда вызывается updatePerson? Этот метод вызывается каждый раз, когда мой сервер получает обновление и передает это обновленное значение моему интерфейсу. Это происходит периодически каждые несколько секунд.

Чего я хочу достичь: Когда пользователь выбирает несколько строк, таблица будет продолжать отображать обновленные значения без отмены выбора выбранных строк.

EDIT: Ниже приведен пример кода, который я использовал для тестирования.

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 для выбора нескольких строк, затем нажмите кнопку редактирования, 3-я строка будет обновлена, но все несколько выбранных строк будут отменены, кроме одной строки.

1 Ответ

0 голосов
/ 27 июня 2018

Думаю, вам будет полезно посмотреть на мой ответ на похожий вопрос: Обновление GlazedList EventList в JTable

Вы должны иметь возможность обновлять элементы в коллекции без необходимости get & set в самом списке.

Кроме того, убедитесь, что вы используете правильную модель выбора событий для получения выбранных элементов. Тогда вам не нужно будет поддерживать объект map.

...