我正在将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方法。被调用时,除最后一个选定行外,我所有的表选择都未被选择。
何时调用“ 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单击选择多行,然后单击“编辑”按钮,第3行将被更新,但除一行以外,所有其他选定行都将被取消选择。
答案 0 :(得分:0)
我认为您可以从我对类似问题的回答中受益:GlazedList update EventList in JTable
您应该能够更新集合中的项目,而不必在列表本身上get
和set
。
此外,请确保使用正确的事件选择模型来获取选定的项目。然后,您将不需要维护map
对象。