0

我正在使用 GlazedLists'EventListEventTableModel在下面的示例中。我不确定它是否有所作为。我有一张桌子,我正在观察选择的变化。当我删除多个项目时,会ListSelectionListener看到多个事件,并且在处理程序内部时,表报告的选定索引与删除发生之前的模型状态匹配,即使模型已经更改。

当我运行以下示例时,列表中添加了 7 个项目。如果我选择最后 2 项,控制台上会出现以下输出:

Selected row count: 2
Item list size: 7
Selected index: 5
Selected index: 6

这就是我所期望的,但是当我删除这两个项目时,我得到以下输出:

Selected row count: 1
Item list size: 5
Selected index: 5

Selected row count: 0
Item list size: 5

由于我正在删除removeAll列表中使用的连续块中的项目,因此我认为这是一个事件,但ListSelectionListener似乎收到通知,就好像它是两个单独的事件一样。如果我删除 4 个项目,侦听器会看到 4 个事件。

表格和模型不同步,但我不知道为什么。如果从列表末尾删除项目,则表报告的选定索引可能大于基础列表大小。基本上,在调用底层模型JTable.getSelectedRows引起的最后一个选择事件之前,返回的索引是不可靠的。removeAll

JTable在列表选择稳定并且将报告正确的选定索引后,如何获得有关选择更改的通知?

import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.gui.AdvancedTableFormat;
import ca.odell.glazedlists.impl.sort.ComparableComparator;
import ca.odell.glazedlists.swing.EventTableModel;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

public class MultiDeleteMain {
    // The number of items that should be added to the model.
    @SuppressWarnings("FieldCanBeLocal")
    private final int itemCount = 7;

    private EventList<Item> itemList;
    private JTable itemTable;

    public static void main(String[] args) {
        new MultiDeleteMain();
    }

    public MultiDeleteMain() {
        SwingUtilities.invokeLater(new Runnable() {
            @SuppressWarnings("ConstantConditions")
            @Override
            public void run() {
                // The delete function needs access to the list and table, so
                // they are stored as instance variables.
                itemList = createItemList();
                itemTable = createItemTable(itemList);

                addListSelectionListenerToItemTable(itemTable);

                JPanel mainPanel = new JPanel(new BorderLayout());
                mainPanel.add(createDeleteButton(), BorderLayout.NORTH);
                mainPanel.add(new JScrollPane(itemTable), BorderLayout.CENTER);

                JFrame mainFrame = new JFrame("Multi-deletion in list test.");
                mainFrame.setContentPane(mainPanel);
                mainFrame.pack();
                mainFrame.setSize(300, mainFrame.getHeight());
                mainFrame.setLocationRelativeTo(null);
                mainFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                mainFrame.setVisible(true);
            }
        });
    }

    private EventList<Item> createItemList() {
        EventList<Item> itemList = new BasicEventList<>();
        for (int i = 0; i < itemCount; i++) {
            itemList.add(new Item("Item " + i));
        }
        return itemList;
    }

    @SuppressWarnings("ConstantConditions")
    private JTable createItemTable(EventList<Item> itemList) {
        JTable itemTable = new JTable(new EventTableModel<>(itemList, new EventTableModelFormat()));
        itemTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        return itemTable;
    }

    private void addListSelectionListenerToItemTable(final JTable itemTable) {
        ListSelectionListener listener = new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if(!e.getValueIsAdjusting()) {
                    System.out.println("Selected row count: " + itemTable.getSelectedRowCount());
                    System.out.println("Item list size: " + itemList.size());
                    for(Integer index : itemTable.getSelectedRows()) {
                        System.out.println("Selected index: " + index);
                    }
                    System.out.println();
                }
            }
        };

        itemTable.getSelectionModel().addListSelectionListener(listener);
    }

    private JButton createDeleteButton() {
        JButton deleteButton = new JButton("Delete");
        deleteButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                deleteSelectedItems();
            }
        });
        return deleteButton;
    }

    @SuppressWarnings("ConstantConditions")
    private void deleteSelectedItems() {
        List<Item> itemsToDelete = new ArrayList<>();
        for (Integer rowIndex : itemTable.getSelectedRows()) {
            int convertedIndex = itemTable.convertRowIndexToModel(rowIndex);
            itemsToDelete.add(itemList.get(convertedIndex));
        }

        itemList.removeAll(itemsToDelete);
        itemTable.revalidate();
        itemTable.repaint();
    }

    // Enum for managing table columns
    private static enum Columns {
        NAME("Name", String.class, new ComparableComparator());

        private final String name;
        private final Class type;
        private final Comparator comparator;

        private Columns(String name, Class type, Comparator comparator) {
            this.name = name;
            this.type = type;
            this.comparator = comparator;
        }
    }

    // Each table holds a list of items.
    private static class Item {
        private final String name;

        private Item(String name) {
            this.name = name;
        }
    }

    // Table format for use with the EventTableModel
    private static class EventTableModelFormat implements AdvancedTableFormat<Item> {
        @Override
        public int getColumnCount() {
            return 1;
        }

        @Override
        public String getColumnName(int i) {
            return Columns.values()[i].name;
        }

        @Override
        public Object getColumnValue(Item item, int i) {
            return item.name;
        }

        @Override
        public Class getColumnClass(int column) {
            return Columns.values()[column].type;
        }

        @Override
        public Comparator getColumnComparator(int column) {
            System.out.println("Asked for comparator.");
            return Columns.values()[column].comparator;
        }
    }
}
4

1 回答 1

1

我们必须知道 EventList 和 EventTableModel 的样子。我敢打赌,EventTableModel 不能保证 deleteAll 方法只传递连续的元素。所以唯一的选择是一个一个地删除它们,为每个它们触发一个单独的事件。

于 2012-09-16T23:13:25.353 回答