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);
}
Проблема: при выборе нескольких строк в таблице и вызывается метод updatePerson, после "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;
}
}
}
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.
1 ответ
Я думаю, что вам будет полезно посмотреть на мой ответ на аналогичный вопрос: GlazedList обновляет EventList в JTable
Вы должны иметь возможность обновлять элементы в коллекции без необходимости get
& set
в самом списке.
Также убедитесь, что вы используете правильную модель выбора событий для получения выбранных элементов. Тогда вам не нужно будет поддерживать map
объект.