Java Swing JTable - 排序后如何获取正确的行索引

3
我在Java中遇到了一个问题。 显示问题的图片 问题是: 我有一个JTable,其中有两列(在图片中为测试目的有4列):一列是复选框,另一列是字符串。 每当用户勾选复选框时,位置列就会计数,因此第一个勾选的复选框将获得位置“1”,第二个勾选的复选框将获得位置“2”,依此类推。
当用户勾选一个具有10个项目的位置为5的复选框时,位置6及以上的行将会减少一个,并且位置5的单元格将设置为空字符串("")。
这个方法可以运行,但我遇到的问题是:
  1. 用户勾选多个复选框,
  2. 然后对表进行排序
  3. 然后尝试勾选任何复选框
这将导致列混乱,如图片所示。
在我的示例图片中,您还可以看到2列: 列Row,在未排序表开始时给出 列RowIndexToModel,显示行的位置但转换为向量内的行,好吧我是这样想的,但似乎并不是。
这是示例类
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

@SuppressWarnings("serial")
public class Example extends JFrame {
    private JTable tbl;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Example frame = new Example();
                frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
    public Example() {
        Object[] colNames = {"Checkbox", "Position"};
        Object[][] rows = {{false, ""}, {false, ""},{false, ""},{false, ""},{false, ""},{false, ""},{false, ""}};
        DefaultTableModel model = new DefaultTableModel(rows, colNames);
        getContentPane().setLayout(new GridBagLayout());

        tbl = new JTable(model)
        {
            @Override
            public Class getColumnClass(int column) {
                switch (column) {
                    case 0:
                        return Boolean.class;
                    case 1:
                        return String.class;
                    default:
                        return String.class;
                }
            }
        };
        tbl.setAutoCreateRowSorter(true);
        tbl.getModel().addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                int row = e.getFirstRow();
                row = tbl.convertRowIndexToModel(row);
                if (e.getColumn() == 0) {
                    TableModel model = (TableModel) e.getSource();
                    Boolean checked = (Boolean) model.getValueAt(row, 0);//getting if boolean got checked or not
                    if (checked) {
                        int maxCount = 0;
                        for (int i = 0; i < model.getRowCount(); i++) {
                            String curValue = (String)model.getValueAt(i, 1);
                            if(curValue != null && !curValue.equals("") && Integer.valueOf(curValue) > maxCount)
                                maxCount = Integer.valueOf(curValue); //get highest number in tbl
                        }
                        maxCount++;
                        model.setValueAt(String.valueOf(maxCount),row, 1); //set highest number + 1
                    } else {
                        String columnString = (String)model.getValueAt(row, 1); //getting position
                        int tmpPos = Integer.valueOf(columnString);

                        for (int index = 0; index < model.getRowCount(); index++) {
                            int indexSorted = tbl.convertRowIndexToModel(index);
                            String curValue = (String)model.getValueAt(indexSorted, 1);
                            //get if current number is higher than unchecked value
                            if (curValue != null && !curValue.equals("") && Integer.valueOf(curValue) > tmpPos) {
                                int curValueToChange = Integer.valueOf(curValue) - 1;
                                model.setValueAt(String.valueOf(curValueToChange),indexSorted, 1); 
                            }
                        }
                        model.setValueAt("",row, 1); 
                    }
                }
            }
        });
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1;
        gbc.weighty = 1;
        JScrollPane scrollPane = new JScrollPane(tbl);
        getContentPane().add(scrollPane, gbc);
    }
}

注意:此代码是为了本示例而编写的,因此请不要惊讶它没有遵循通用编码标准。如果我的代码让你的眼睛疼痛,请原谅。
感谢任何帮助!
编辑:我尝试为问题提供更好的概述结构,并使代码更易读(我认为)。如果难以理解,我将尝试回答问题。
编辑2:添加了一个简单的JFrame代码,这样您可以复制并粘贴代码以查看问题。

2
为了更快地获得帮助,请发布一个[MCVE]或简短,自包含,正确的示例 - Andrew Thompson
2
请重新阅读@AndrewThompson在评论中提供给您的重要链接,因为我认为您可能会错过那里最重要的要点。为了获得最好的帮助,您需要发布一个小的可编译和可运行程序。这是足够小以便将其完整地作为代码格式化文本发布的代码,我们可以将其复制到我们的IDE中,它可以为我们编译,运行并演示您的问题。 - Hovercraft Full Of Eels
3
补充一下 @HovercraftFullOfEels 的建议。如果一个最小化可复现代码样例(MCVE)/ 最短自给程序(SSCCE)有200行代码,这些代码都是必要的,可以让代码样例正常编译并演示问题,那么在我看来它仍然是MCVE / SSCCE。之所以这些描述中使用了“最小/最短”这些词语,是因为人们经常会留下大量与问题无关的代码。通常情况下,删除不必要的代码会间接地导致提问者自己发现问题。但是,如果代码被精简到最小/最短而没有清晰地表达问题,那么最重要的部分就... - Andrew Thompson
2
如同在各自短语的其余部分中所提到的一样,让它成为我们都可以复制、粘贴、运行并实际看到问题的代码,无需任何进一步的更改或添加。如果您在这两个链接中读到了任何不清楚的内容,请不要害怕询问。我们中的任何一个人以及许多其他人都可以进一步解释。 - Andrew Thompson
1
@AndrewThompson 感谢您的帮助,我已经弄清楚了我的问题所在,原来是我误解了“convertRowIndexToModel”的含义,在加上它之后,现在程序可以按照我想要的方式运行了。 - SergSam
显示剩余4条评论
1个回答

2
我发现我的示例显示错误的值,原因是:
当我转换该行时,
tbl.convertRowIndexToModel(row);

我得到了错误的行索引。
在我删除了两行将行索引转换的代码后,我得到了正确的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接