【问题标题】:Glazed List JTable Selection Lost When Row Is Updated更新行时,釉面列表 JTable 选择丢失
【发布时间】:2014-09-11 14:46:45
【问题描述】:

我有一个 JTable 显示由 Glazed List 支持的数据。表格选择在非常特定的条件下丢失。必须更新所选行,以便更改排序的列,以便所选行将移动到新位置。

我相信我遇到了这个 GlazedList 错误,但我找不到解决方法:https://java.net/jira/browse/GLAZEDLISTS-194

我创建了一些演示该问题的源代码:

public class SelectionLost {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                /*
                 * Create and set up the table.
                 */
                final JTable table = new JTable();
                final EventList<DisplayElement> data = new BasicEventList<>();
                ObservableElementList<DisplayElement> observeData = 
                        new ObservableElementList<>(data, new DisplayConnector());
                final SortedList<DisplayElement> sortedData = 
                        new SortedList<>(observeData);
                sortedData.setMode(SortedList.STRICT_SORT_ORDER);
                //populate our list with some data.
                data.add(new DisplayElement("a", "a"));
                data.add(new DisplayElement("b", "b"));
                data.add(new DisplayElement("c", "c"));
                data.add(new DisplayElement("d", "d"));
                //Set up the table models.
                AdvancedTableModel<DisplayElement> model
                        = GlazedListsSwing.eventTableModelWithThreadProxyList(sortedData, new DisplayTableFormat());
                table.setModel(model);
                final AdvancedListSelectionModel<DisplayElement> select
                        = GlazedListsSwing.eventSelectionModelWithThreadProxyList(sortedData);
                table.setSelectionModel(select);
                TableComparatorChooser<DisplayElement> tc = TableComparatorChooser.install(
                        table, sortedData, TableComparatorChooser.MULTIPLE_COLUMN_MOUSE_WITH_UNDO);
                //sort on the first column
                tc.appendComparator(0, 0, false);
                //select the first row
                table.getSelectionModel().setSelectionInterval(0, 0);

                /*
                 * Create UI elements
                 */
                JFrame frame = new JFrame();
                JPanel panel = new JPanel(new BorderLayout());
                frame.add(panel);
                JScrollPane scroll = new JScrollPane(table);
                panel.add(scroll);
                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                final Random r = new Random();
                /*
                 * Create a timer which will change the elements data. When the selected
                 * element's data is changed so that it moves into a new index position, 
                 * the selection is lost.
                 */
                TimerTask tt = new TimerTask() {
                    @Override
                    public void run() {
                        data.getReadWriteLock().writeLock().lock();
                        try{
                            int row = r.nextInt(data.size());
                            int col = r.nextInt(2);
                            Character c = (char)(r.nextInt(26)+'a');
                            DisplayElement d = data.get(row);
                            if(col == 0)
                                d.setFirst(c.toString());
                            else
                                d.setSecond(c.toString());
                        }
                        finally{
                            data.getReadWriteLock().writeLock().unlock();
                        }
                    }
                };
                java.util.Timer t = new java.util.Timer();
                t.schedule(tt, 250, 250);
            }
        });
    }
    /*
     * These are the data elements stored in the table
     */
    public static class DisplayElement implements Comparable<DisplayElement>{
        private String first, second;
        private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

        public DisplayElement(String first, String second) {
            this.first = first;
            this.second = second;
        }

        public String getFirst() {
            return first;
        }

        public void setFirst(String first) {
            this.first = first;
            pcs.firePropertyChange("first", null, null);
        }

        public String getSecond() {
            return second;
        }

        public void setSecond(String second) {
            this.second = second;
            pcs.firePropertyChange("second", null, null);

        }

        @Override
        public int compareTo(DisplayElement o) {
            int comp = first.compareTo(o.first);
            if(comp != 0)
                return comp;
            return second.compareTo(o.second);
        }
        public void addPropertyChangeListener(PropertyChangeListener l){
            pcs.addPropertyChangeListener(l);
        }
        public void removePropertyChangeListener(PropertyChangeListener l ){
            pcs.removePropertyChangeListener(l);
        }
    }
    /*
     * Table format for glazed lists
     */
    public static class DisplayTableFormat implements AdvancedTableFormat<DisplayElement>, WritableTableFormat<DisplayElement>{
        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public String getColumnName(int i) {
            if(i == 0 )
                return "first";
            else
                return "second";
        }

        @Override
        public Object getColumnValue(DisplayElement e, int i) {
            if(i == 0)
                return e.first;
            else
                return e.second;
        }

        @Override
        public Class getColumnClass(int i) {
            return String.class;
        }

        @Override
        public Comparator getColumnComparator(int i) {
            return GlazedLists.comparableComparator();
        }

        @Override
        public boolean isEditable(DisplayElement e, int i) {
            return true;
        }

        @Override
        public DisplayElement setColumnValue(DisplayElement e, Object o, int i) {
            if(i == 0)
                e.first = (String) o;
            else
                e.second = (String)o;
            return e;
        }
    };
    /*
     * Connector for observable lists.
     */
    public static class DisplayConnector implements ObservableElementList.Connector<DisplayElement>{
        ObservableElementList<? extends DisplayElement> list;
        PropertyChangeListener myListener = new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                list.elementChanged(evt.getSource());
            }
        };
        @Override
        public EventListener installListener(DisplayElement e) {
            e.addPropertyChangeListener(myListener);
            return myListener;
        }

        @Override
        public void uninstallListener(DisplayElement e, EventListener el) {
            e.removePropertyChangeListener(myListener);
        }

        @Override
        public void setObservableElementList(ObservableElementList<? extends DisplayElement> oel) {
            list = oel;
        }
    }
}

【问题讨论】:

    标签: java swing jtable glazedlists


    【解决方案1】:

    在尝试了无数次修复后,我终于找到了解决问题的方法。我创建了一个恢复选择的侦听器。唯一的缺点是用户不能再通过 CTRL+单击来“取消选择”一行。如果有人能想到更好的解决方案,我会很高兴看到它。我觉得这个有点hacky。

        /*
         * This listener fixes the problem where we would lose selection.
         * Note that it prevents the user from "unselecting" a row.
         */
        public static class GlazedListBug194Listener <T> implements ListSelectionListener {
            private T lastSelectedElement;
            private final JTable table;
            private final AdvancedTableModel<T> model;
            private final AdvancedListSelectionModel<T> select;
    
            public GlazedListBug194Listener(JTable table, 
                    AdvancedTableModel<T> model, 
                    AdvancedListSelectionModel<T> select) {
                this.table = table;
                this.model = model;
                this.select = select;
    
            }
    
            @Override
            public void valueChanged(ListSelectionEvent e) {
                int selectedRow = table.convertRowIndexToModel(table.getSelectedRow());
                if(selectedRow < 0){
                    if(table.getRowCount() == 0){
                        //table was cleared
                        lastSelectedElement = null;
                    }
                    else{
                        //restore selection
                        for(int i = 0; i < table.getRowCount(); i++){
                            if(model.getElementAt(i) == lastSelectedElement){
                                select.setSelectionInterval(i, i);
                                break;
                            }
                        }
                    }
                }
                else{
                    lastSelectedElement = model.getElementAt(selectedRow);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多