排序表的JTable选择间隔问题



我有一个JTable,它使用RowSorter进行排序和过滤,并实时更新。当用户试图用鼠标(点击+拖动行)或键盘(多次按下SHIFT+向下箭头)创建选择间隔时,我遇到了一个问题。

一旦表模型更新事件发生,选择间隔的开始和结束就会损坏。我发现,如果一个表被排序,并且有多个选定的行,则选择模型会触发多个列表选择事件,清除这些事件,然后在每次表模型更新时重新创建选择。

如果一次选择多行,那么一切都很好。用户选择的内容保持选中状态。但是,如果用户试图通过在多行上单击并向下拖动鼠标来创建选择间隔,则会正确选择这些行,直到触发表模型更新事件。然后,所选内容从当前选定的行开始构建。

我附上了一个小的演示应用程序。尝试用鼠标选择多行-每秒钟所选内容都会被破坏。。。。

这似乎是Java类中的一个错误(或不需要的行为)。我希望有人能提供一个创造性的解决方案。

    public class TableTest extends JFrame {
    private static final long serialVersionUID = 1L;
    public TableTest() {
        super("Table Selection Problem");
        setBounds(50, 50, 800, 600);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        // Create a table model
        final DefaultTableModel tableModel = new DefaultTableModel(40,10);
        // Create table row sorter sorted on column 1
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel);
        sorter.setSortsOnUpdates(true);
        sorter.setSortKeys(Arrays.asList(new RowSorter.SortKey(1,SortOrder.DESCENDING)));
        // Create a table and bind the sorter
        JTable table = new JTable(tableModel);
        table.setRowSorter(sorter);
        // Bind a list selection listener, this doesn't do anything besides showing the selection change(s) on every table model update
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                System.out.println(e); 
            }
        });

        // place the table in the frame
        getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
        // Simulate some application events that trigger a table update...
        new Thread() {
            public void run() {
                try {
                    final Random r = new Random();
                    for(int x = 0; x < 1000; x++) {
                        // update a table cell (not even an add or delete)
                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                tableModel.setValueAt(r.nextInt(1000), r.nextInt(40), r.nextInt(10));
                            }
                        });
                        // wait 1 second before next table update
                        Thread.sleep(1000);
                    }
                } catch(Throwable t) {
                    t.printStackTrace();
                }
            }
        }.start();      
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                (new TableTest()).setVisible(true);                     
            }
        });     
    }
}

当我在Windows 7上使用JDK7运行您的代码时,我发现setSortsOnUpdates(...)导致表中的数据出现问题。也就是说,我让代码运行了一段时间,我注意到第1列中没有显示任何值。然后我增加了框架的宽度,突然值按排序顺序出现了。因此,由于某种原因,即使数据发生了更改,表也没有被重新绘制。当我评论setSortsOnUpdates(...)时,对TableModel的更改立即出现。我不知道问题出在哪里。

因此,我更改了在数据更改时手动调用排序的方法。然而,我只是在ListSelectionListener没有调整时才进行排序。这是代码:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.Arrays;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
    public class TableTest5 extends JFrame {
    private static final long serialVersionUID = 1L;
    private boolean isAdjusting = false;
    private boolean isModelChanged = false;
    TableRowSorter<TableModel> sorter;
    final Random r = new Random();
    public TableTest5() {
        super("Table Selection Problem");
        setBounds(50, 50, 800, 600);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        // Create a table model
        final DefaultTableModel tableModel = new DefaultTableModel(30,3);
        // Create table row sorter sorted on column 1
//        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel);
        sorter = new TableRowSorter<TableModel>(tableModel);
        sorter.setSortsOnUpdates(true);
        sorter.setSortKeys(Arrays.asList(new RowSorter.SortKey(1,SortOrder.DESCENDING)));
        // Create a table and bind the sorter
        JTable table = new JTable(tableModel);
        table.setRowSorter(sorter);
        // Bind a list selection listener, this doesn't do anything besides showing the selection change(s) on every table model update
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                isAdjusting = e.getValueIsAdjusting();
                if (!isAdjusting && isModelChanged)
                {
                    isModelChanged = false;
                    sorter.sort();
                }
            }
        });

        // place the table in the frame
        getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
        // Simulate some application events that trigger a table update...
        new Thread() {
            public void run() {
                try {
                    //final Random r = new Random();
                    for(int x = 0; x < 1000; x++) {
                        // update a table cell (not even an add or delete)
                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                int value = r.nextInt(1000);
                                int row = r.nextInt(30);
                                int column = r.nextInt(5);
                                System.out.println(value + " : " + row + " : " + column);
                                tableModel.setValueAt(value, row, column);
                                if (!isAdjusting)
                                    sorter.sort();
                                else
                                    isModelChanged = true;
                            }
                        });
                        // wait 1 second before next table update
                        Thread.sleep(1000);
                    }
                } catch(Throwable t) {
                    t.printStackTrace();
                }
            }
        }.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                (new TableTest5()).setVisible(true);
            }
        });
    }
}

您可能需要考虑使用TableModelListener来侦听TableModel更改,以手动调用排序。

相关内容

  • 没有找到相关文章

最新更新