0

私はGlazedListsを使用EventListEventTableModelています。以下の例では。それが違いを生むかどうかはわかりません。選択の変更を監視しているテーブルがあります。複数のアイテムを削除するListSelectionListenerと、複数のイベントが表示され、ハンドラー内では、モデルが既に変更されていても、テーブルによって報告された選択されたインデックスが、削除が発生する前のモデルの状態と一致します。

以下の例を実行すると、7つのアイテムがリストに追加されます。最後の2つの項目を選択すると、次の出力がコンソールに表示されます。

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

それは私が期待していることですが、これら2つのアイテムを削除すると、次の出力が得られます。

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

Selected row count: 0
Item list size: 5

removeAllリストを使用して連続ブロック内のアイテムを削除しているので、これは1つのイベントだと思いますが、 ListSelectionListener2つの別々のイベントであるかのように通知されているようです。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メソッドが連続する要素のみを渡すという保証はありません。したがって、唯一のオプションは、それらを1つずつ削除し、それぞれに個別のイベントを発生させることです。

于 2012-09-16T23:13:25.353 に答える