简体   繁体   English

GlazedList更新JTable中的EventList

[英]GlazedList update EventList in JTable

How can I update EventList list to update JTable ? 如何更新EventList列表以更新JTable This is what I do: 这是我的工作:

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

The probem is when i filter the records in table, and select a record and trying to update it, it create a new record in the table instead 当我过滤表中的记录并选择一条记录并尝试对其进行更新时,它会在表中创建新记录

int updatedRow = tblMembers.convertRowIndexToModel(tblMembers.getSelectedRow());
eventList.set(updatedRow, updatedMember);

Once you're using GlazedLists to power your JTable then you should only use EventTableModel and EventSelectionModel to interact with your JTable . 一旦使用GlazedLists为JTable供电,则应仅使用EventTableModelEventSelectionModelJTable进行交互。 The mistake you've made is to query the JTable directly for the selected row and get its index - but the JTable doesn't understand that it's backed by an EventList which maybe sorting/filtering items within. 您犯的错误是直接查询JTable以获取选定的行并获取其索引-但是JTable无法理解它是否由EventList支持,后者可能对其中的项目进行排序/过滤。 Therefore row i in the JTable will not necessarily correspond to element i in your EventList. 因此,JTable中的第i行不一定与您的EventList中的元素i相对应。

In your code you have actually set up an EventSelectionModel, now it's just a matter of using it. 在您的代码中,您实际上已经设置了一个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);
     }
}

You have to remember that JTables support multiple row selections (although that can be configured allow only single row selection) and therefore the EventSelectionModel sensibly will return an EventList of all the selected rows, even if only one is selected. 您必须记住,JTables支持多个行选择(尽管可以将其配置为仅允许单行选择),因此EventSelectionModel明智地将返回所有选定行的EventList,即使仅选择了一个。 Therefore you need to iterate over the returned list. 因此,您需要遍历返回的列表。 There is an additional convenience that the EventList containing the selected items is backed by the source EventList, so you can make changes directly to that sub-list. 另外一个方便之处在于,包含选定项目的EventList由源EventList支持,因此您可以直接对该子列表进行更改。

Advanced 高级

Of course EventLists are great for observing the fundamental changes to a list: deletion, insertion, updating (ie replacing an existing object at index i with another object). 当然,EventList非常适合观察列表的基本变化:删除,插入,更新(即,将索引i处的现有对象替换为另一个对象)。 However, wouldn't it be great if instead of calling selectedMembers.set() , we could update an object within an EventList directly and then let GlazedLists detect that property change? 但是,如果不是直接调用selectedMembers.set()而是直接在EventList中更新对象,然后让GlazedLists检测该属性更改,那不是很好吗?

Well that's possible too. 嗯,那也是可能的。 There's a useful list type called ObservableElementList and here it will listen to property changes for each object it contains and refresh accordingly. 有一个有用的列表类型,称为ObservableElementList ,在这里它将侦听其包含的每个对象的属性更改,并相应地刷新。 This is much more convenient than having to locate the object within the list and called eventList.set() . 这比必须在列表中找到名为eventList.set()的对象要方便得多。

You first need to make your class support property listeners, ie, is a proper Java bean, and then use a ObservableElementList.Connector . 首先,需要使您的类支持属性侦听器,即它是正确的Java Bean,然后使用ObservableElementList.Connector

I've created a small but complete example of this in action. 我已经创建了一个小而完整的实例来说明这一点。 In this example there is a text input at the top for filtering, a table containing a short list of authors, and a button at the bottom which will update the name of any selected row. 在此示例中,顶部有一个用于过滤的文本输入,一个包含作者简短列表的表以及一个在底部的按钮,它将更新任何选定行的名称。

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM