Java 行选择不随JTable中的行移动而移动

Java 行选择不随JTable中的行移动而移动,java,swing,jtable,local-variables,listselectionlistener,Java,Swing,Jtable,Local Variables,Listselectionlistener,我有以下代码: import java.awt.BorderLayout; import java.awt.Dimension; import java.util.Vector; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.UIManager; import ja

我有以下代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.DefaultTableModel;

public class NewClass1 extends JFrame {
    private JTable table;
    private JScrollPane scrollPane;
    private DefaultTableModel defaultTableModel;

    public NewClass1() {
        setLocationByPlatform(true);
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(600, 400));
        setTitle("Table Issues");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        createTableModel();
        table = new JTable(defaultTableModel);

        scrollPane = new JScrollPane(table);

        getContentPane().add(scrollPane, BorderLayout.CENTER);

        pack();
    }

    private void createTableModel() {
        Vector cols = new Vector();
        cols.add("A");

        Vector rows = new Vector();
        for (int i = 0; i < 50; i++) {
            Vector row = new Vector();
            row.add((i + 1) + "");
            rows.add(row);
        }

        defaultTableModel = new DefaultTableModel(rows, cols) {
            Class[] types = new Class[]{
                String.class
            };

            @Override
            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(new NimbusLookAndFeel());
        } catch (Exception e) {
        }

        final NewClass1 nc = new NewClass1();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                nc.setVisible(true);
            }
        });

        while (true) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    int row = (int) (Math.random() * 50);
                    int move = (int) (Math.random() * 50);

                    nc.defaultTableModel.moveRow(row, row, move);
                }
            });
            try{
                Thread.sleep(1000);
            }catch(Exception e){
            }
        }
    }
}
导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.util.Vector;
导入javax.swing.JFrame;
导入javax.swing.JScrollPane;
导入javax.swing.JTable;
导入javax.swing.SwingUtilities;
导入javax.swing.UIManager;
导入javax.swing.plaf.nimbus.NimbusLookAndFeel;
导入javax.swing.table.DefaultTableModel;
公共类NewClass1扩展了JFrame{
专用JTable表;
私有JScrollPane滚动窗格;
私有DefaultTableModel DefaultTableModel;
公共服务类别1(){
setLocationByPlatform(真);
setLayout(新的BorderLayout());
setPreferredSize(新尺寸(600400));
setTitle(“表格发行”);
setDefaultCloseOperation(关闭时退出);
createTableModel();
table=新的JTable(defaultTableModel);
scrollPane=新的JScrollPane(表);
getContentPane().add(滚动窗格,BorderLayout.CENTER);
包装();
}
私有void createTableModel(){
向量cols=新向量();
列加(“A”);
向量行=新向量();
对于(int i=0;i<50;i++){
向量行=新向量();
行。添加((i+1)+“”);
行。添加(行);
}
defaultTableModel=新的defaultTableModel(行、列){
类[]类型=新类[]{
String.class
};
@凌驾
公共类getColumnClass(int columnIndex){
返回类型[列索引];
}
@凌驾
公共布尔值可编辑(int行,int列){
返回false;
}
};
}
公共静态void main(字符串[]args){
试一试{
setLookAndFeel(新的NimbusLookAndFeel());
}捕获(例外e){
}
最终NewClass1 nc=新NewClass1();
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
nc.setVisible(真);
}
});
while(true){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
int行=(int)(Math.random()*50);
int move=(int)(Math.random()*50);
nc.defaultTableModel.moveRow(行,行,移动);
}
});
试一试{
睡眠(1000);
}捕获(例外e){
}
}
}
}
请运行上述代码并选择行

我的问题是行移动,行选择不移动。它保持在固定的位置。假设我选择了列值为25的行,则在行移动后,所选行的列值必须为25

请帮我做这个


我真正的问题是,用户将选择行并单击菜单来执行操作,同时其他线程可能已经移动了行,并且执行的操作将在实际行以外的其他行上。

最简单的方法是在
列表选择模型
之外的某个位置记住所选行,并在
表格模型
更改时调整所选行。例如,您可以这样做:

public class NewClass1 extends JFrame {
    private JTable table;
    private DefaultTableModel defaultTableModel;
    private JScrollPane scrollPane;

    private class SelectionHelper implements ListSelectionListener, TableModelListener {
        private Object selectedRow;

        @Override
        public void valueChanged(ListSelectionEvent event) {
            if (!event.getValueIsAdjusting()) return;
            int selectedIndex = table.getSelectedRow();
            if (selectedIndex >= 0) {
                selectedRow = defaultTableModel.getDataVector().get(selectedIndex);
            } else {
                selectedRow = null;
            }
        }

        @Override
        public void tableChanged(TableModelEvent event) {
            if (selectedRow == null) return;
            int selectedIndex = defaultTableModel.getDataVector().indexOf(selectedRow);
            table.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex);
        }
    }

    public NewClass1() {
        // ...
        createTableModel();
        table = new JTable(defaultTableModel);

        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        SelectionHelper helper = new SelectionHelper();
        table.getModel().addTableModelListener(helper);
        table.getSelectionModel().addListSelectionListener(helper);
        // ...
    }
    // ...
}

但是请注意,您应该调整此代码以供生产使用,例如在线程安全性或可移植性方面(使用内部类中的
defaultTableModel
属性是不好的样式)。

,作者@GuillaumePolet@mKorbel这里的问题是模型的内容在变化,因此,
convertRowIndexToModel
本身并不能完成这项工作,但我同意如果
javax.swing.table.DefaultTableModel.moveRow
是正在发生的一切,那么使用
javax.swing.RowSorter
将是一个更好的方法——我理解这是一个通用模型更改的示例。请回答一个问题,为什么使用if(!event.getValueIsAdjusting())返回;这实际上不是必需的,但更为简洁:选择新行时会触发两次“valueChanged”事件:一次让您知道旧行未被选中,一次让您知道新行已被选中。只需将行注释出来,并在其中放入一条
print
语句,它就会变得清晰。