GlazedList обновляет EventList в JTable
Как я могу обновить EventList
список для обновления JTable
? Вот что я делаю:
String[] headers = new String[]{"MNO", "NAME", "ID/REG No", "PHONE"};
String[] properties = new String[]{"milkNo", "fullName", "nationalId", "phone1"};
TextFilterator<Member> personTextFilterator = new TextFilterator<Member>() {
@Override
public void getFilterStrings(List list, Member m) {
list.add(m.getFullName());
list.add(m.getMilkNo());
list.add(m.getNationalId());
list.add(m.getPhone1());
}
};
MatcherEditor<Member> textMatcherEditor = new TextComponentMatcherEditor<Member>(txtFilter, personTextFilterator);
FilterList<Member> filterList = new FilterList<Member>(eventList, textMatcherEditor);
TableFormat tf = GlazedLists.tableFormat(properties, headers);
model = new EventTableModel<Member>(filterList, tf);
selectionModel = new EventSelectionModel<Member>(filterList);
tblMembers.setSelectionModel(selectionModel);
tblMembers.setModel(model);
Проблема в том, что когда я фильтрую записи в таблице, выбираю запись и пытаюсь ее обновить, вместо этого создается новая запись в таблице.
int updatedRow = tblMembers.convertRowIndexToModel(tblMembers.getSelectedRow());
eventList.set(updatedRow, updatedMember);
1 ответ
Как только вы используете GlazedLists для питания вашего JTable
тогда вы должны использовать только EventTableModel
а также EventSelectionModel
взаимодействовать с вашим JTable
, Ошибка, которую вы сделали, заключается в том, что вы запросили JTable напрямую для выбранной строки и получили ее индекс - но JTable не понимает, что он поддерживается EventList, который может сортировать / фильтровать элементы внутри. Поэтому строка i в JTable не обязательно будет соответствовать элементу i в вашем EventList.
В вашем коде вы фактически настроили EventSelectionModel, теперь это просто вопрос его использования.
if (!selectionModel.isSelectionEmpty()) {
EventList<Member> selectedMembers = selectionModel.getSelected();
for (int i = 0; i<selectedMembers.size(); i++) {
Member member = selectedMembers.get(i);
//update accordingly...
//member.setXXX(...);
selectedMembers.set(i, member);
}
}
Вы должны помнить, что JTables поддерживают множественный выбор строк (хотя это можно настроить, разрешая выбор только одной строки), и поэтому EventSelectionModel будет разумно возвращать EventList всех выбранных строк, даже если выбрана только одна. Поэтому вам нужно перебрать возвращенный список. Дополнительным удобством является то, что EventList, содержащий выбранные элементы, поддерживается исходным EventList, так что вы можете вносить изменения непосредственно в этот подсписок.
продвинутый
Конечно, EventList отлично подходят для наблюдения за фундаментальными изменениями в списке: удаление, вставка, обновление (т.е. замена существующего объекта с индексом i другим объектом). Однако не было бы замечательно, если бы вместо звонка selectedMembers.set()
, мы могли бы обновить объект в EventList напрямую, а затем позволить GlazedLists обнаружить это изменение свойства?
Ну, это тоже возможно. Есть полезный тип списка ObservableElementList
и здесь он будет прослушивать изменения свойств для каждого объекта, который он содержит, и обновлять соответственно. Это гораздо удобнее, чем найти объект в списке и вызвать eventList.set()
,
Сначала вам нужно сделать так, чтобы ваш класс поддерживал свойство слушателей, т. Е. Был правильным Java-бином, а затем использовал ObservableElementList.Connector
,
Я создал небольшой, но полный пример этого в действии. В этом примере вверху есть текстовый ввод для фильтрации, таблица с кратким списком авторов и кнопка внизу, которая обновит имя любой выбранной строки.
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.ObservableElementList;
import ca.odell.glazedlists.TextFilterator;
import ca.odell.glazedlists.matchers.MatcherEditor;
import ca.odell.glazedlists.swing.EventSelectionModel;
import ca.odell.glazedlists.swing.EventTableModel;
import ca.odell.glazedlists.swing.TextComponentMatcherEditor;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
public class GlazedListSelectionObservable {
private JFrame frame;
private JTable table;
private JTextField txtInput;
private EventList<Person> people;
private EventSelectionModel<Person> selectionModel;
public GlazedListSelectionObservable() {
setupGui();
setupGlazedLists();
populatedList();
frame.setVisible(true);
}
private void setupGui() {
frame = new JFrame("GlazedLists Selection Example");
frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
txtInput = new JTextField();
table = new JTable();
frame.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
JButton updateTableButton = new JButton("Update selected row");
updateTableButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!selectionModel.isSelectionEmpty()) {
EventList<Person> selectedPeople = selectionModel.getSelected();
for (Person person: selectedPeople) {
person.setFirstName("David");
person.setLastName("Baldacci");
}
}
}
});
frame.getContentPane().add(txtInput, BorderLayout.NORTH);
frame.getContentPane().add(updateTableButton, BorderLayout.SOUTH);
}
private void populatedList() {
people.add(new Person("John", "Grisham"));
people.add(new Person("Patricia", "Cornwell"));
people.add(new Person("Nicholas", "Sparks"));
people.add(new Person("Andy", "Weir"));
people.add(new Person("Elizabeth", "George"));
}
private void setupGlazedLists() {
people = new BasicEventList<Person>();
MatcherEditor<Person> textMatcherEditor = new TextComponentMatcherEditor<Person>(txtInput, new PersonTextFilterator());
ObservableElementList.Connector<Person> personConnector = GlazedLists.beanConnector(Person.class);
EventList<Person> observedPeople = new ObservableElementList<Person>(people, personConnector);
FilterList<Person> filteredPeople = new FilterList<Person>(observedPeople, textMatcherEditor);
EventTableModel model = new EventTableModel(filteredPeople, GlazedLists.tableFormat(new String[]{"firstName", "lastName"} , new String[]{"First Name", "Last Name"}));
selectionModel = new EventSelectionModel<Person>(filteredPeople);
table.setModel(model);
table.setSelectionModel(selectionModel);
}
class PersonTextFilterator implements TextFilterator<Person> {
@Override
public void getFilterStrings(List<String> list, Person person) {
list.add(person.getFirstName());
list.add(person.getLastName());
}
}
public class Person {
private String firstName;
private String lastName;
private final PropertyChangeSupport support = new PropertyChangeSupport(this);
public Person() {
}
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setFirstName(String firstName) {
final String oldFirstName = this.firstName;
this.firstName = firstName;
support.firePropertyChange("firstName", oldFirstName, firstName);
}
public void setLastName(String lastName) {
final String oldLastName = this.lastName;
this.lastName = lastName;
support.firePropertyChange("lastName", oldLastName, lastName);
}
public void addPropertyChangeListener(PropertyChangeListener l) {
support.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
support.removePropertyChangeListener(l);
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GlazedListSelectionObservable();
}
});
}
}