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

}
Другие вопросы по тегам