Java 已排序表的JTable选择间隔问题
我有一个JTable,它使用RowSorter进行排序和过滤,并以实时方式进行更新。当用户试图使用鼠标(单击+拖动行)或键盘(多次按住SHIFT+向下箭头键)创建选择间隔时,我遇到了一个问题 一旦发生表模型更新事件,选择间隔开始和结束就会损坏。我发现,如果对一个表进行了排序,并且有多个选定行,则选择模型将触发多个列表选择事件,这些事件将被清除,然后在每次表模型更新时重新创建选择 如果一次选择一行,则所有行都正常。用户选择的内容保持选中状态。但是,如果用户试图通过在多行上单击并向下拖动鼠标来创建选择间隔,则会正确选择这些行,直到触发表模型更新事件。然后,选择将从当前选定的行开始构建 我附上了一个小的演示应用程序。尝试使用鼠标选择多行-每秒钟选择内容都会被损坏 这似乎是Java类中的一个bug(或不需要的行为)。我希望有人能提供创造性的解决方案Java 已排序表的JTable选择间隔问题,java,swing,jtable,selection,rowsorter,Java,Swing,Jtable,Selection,Rowsorter,我有一个JTable,它使用RowSorter进行排序和过滤,并以实时方式进行更新。当用户试图使用鼠标(单击+拖动行)或键盘(多次按住SHIFT+向下箭头键)创建选择间隔时,我遇到了一个问题 一旦发生表模型更新事件,选择间隔开始和结束就会损坏。我发现,如果对一个表进行了排序,并且有多个选定行,则选择模型将触发多个列表选择事件,这些事件将被清除,然后在每次表模型更新时重新创建选择 如果一次选择一行,则所有行都正常。用户选择的内容保持选中状态。但是,如果用户试图通过在多行上单击并向下拖动鼠标来创建选
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);
}
});
}
}
公共类TableTest扩展JFrame{
私有静态最终长serialVersionUID=1L;
公共表格测试(){
超级(“表格选择问题”);
立根(50,50800600);
setDefaultCloseOperation(关闭时退出);
//创建一个表模型
最终DefaultTableModel tableModel=新DefaultTableModel(40,10);
//创建按列1排序的表行分类器
TableRowSorter分拣机=新的TableRowSorter(tableModel);
分拣机。设置分拣更新(真);
sorter.SetSortKey(Arrays.asList(新行sorter.SortKey(1,SortOrder.DESCENDING));
//创建表格并绑定分拣机
JTable table=新的JTable(tableModel);
表.SetRow分拣机(分拣机);
//绑定一个列表选择监听器,除了在每次表模型更新时显示选择更改之外,这不会做任何事情
table.getSelectionModel().addListSelectionListener(新ListSelectionListener()){
@凌驾
public void值已更改(ListSelectionEvent e){
系统输出打印ln(e);
}
});
//把桌子放在架子上
getContentPane().add(新的JScrollPane(表),BorderLayout.CENTER);
//模拟一些触发表更新的应用程序事件。。。
新线程(){
公开募捐{
试一试{
最终随机r=新随机();
对于(int x=0;x<1000;x++){
//更新表格单元格(甚至不是添加或删除)
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
tableModel.setValueAt(r.nextInt(1000)、r.nextInt(40)、r.nextInt(10));
}
});
//等待1秒钟,然后再进行下一次表更新
睡眠(1000);
}
}捕获(可丢弃的t){
t、 printStackTrace();
}
}
}.start();
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
(新建TableTest()).setVisible(true);
}
});
}
}
当我在Windows 7上使用JDK7运行您的代码时,我发现设置端口更新(…)
导致表中的数据出现问题。也就是说,我让代码运行了一段时间,我注意到第1列中没有显示任何值。然后我增加了帧的宽度,突然这些值以排序的顺序出现。因此,出于某种原因,即使数据发生了更改,表也没有被重新绘制。当我评论setSortsUpdates(…)
时,立即出现了对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);
}
});
}
}
import java.awt.*;
导入java.awt.event.*;
导入java.util.Random;
导入java.util.array;
导入javax.swing.*;
导入javax.swing.table.*;
导入javax.swing.event.*;
公共类TableTest5扩展了JFrame{
私有静态最终长serialVersionUID=1L;
私有布尔值isAdjusting=false;
私有布尔值isModelChanged=false;
台式分拣机;
最终随机r=新随机();
公共表test5(){
超级(“表格选择问题”);
立根(50,50800600);
setDefaultCloseOperation(关闭时退出);
//创建一个表模型
最终DefaultTableModel tableModel=新DefaultTableModel(30,3);
//创建按列1排序的表行分类器
//TableRowSorter分拣机=新的TableRowSorter(tableModel);
分拣机=新的表格行分拣机(表格型号);
分拣机。设置分拣更新(真);
sorter.SetSortKey(Arrays.asList(新行sorter.SortKey(1,SortOrder.DESCENDING));
//创建表格并绑定分拣机
JTable table=新的JTable(tableModel);
表.SetRow分拣机(分拣机);
//绑定一个列表选择监听器,除了在每次表模型更新时显示选择更改之外,这不会做任何事情
table.getSelectionModel().addListSelectionListener(新ListSelectionListener()){
@凌驾
public void值已更改(ListSelectionEvent e){
isAdjusting=e.getValueIsAdjusting();
如果(!isAdjusting&&isModelChanged)
{
isModelChanged=fa