简体   繁体   English

Java-JTable-getSelectedRow()中的数据错误

[英]Java - JTable - Wrong data in getSelectedRow()

I have made search everywhere so this is my 'last' hope. 我已经到处搜索,所以这是我的“最后”希望。

I have a JTable which I populate with some CSV values. 我有一个JTable,其中填充了一些CSV值。 When I performe an action to remove selected rows, it does not remove all ... To understand better follow the debugs: 当我执行删除选定行的操作时,它不会删除所有...为了更好地理解,请遵循以下调试信息:

Begin (total selected): 6
Removed index: 6
Removed index: 4
Removed index: 3
Removed index: 2
Removed index: 1
End (total selected): 0

But is remaining one.... Note that 5 of them was removed, but one was skipped... I don't understand why this is happening. 但是剩下的就是...。请注意,其中有5个已删除,但其中一个被跳过了...我不明白为什么会这样。

My code: 我的代码:

    // I got a List<LikedHashMap<String, String>> data
    // where I store my CSV data.
    // To populate the JTable I remove from this list (data)
    // and insert to JTable.
    // Before remove from JTable, I put back the row into data.
    // THIS LOOP IS WORKING PRETTY WELL.
    for (int row : this.table.getSelectedRows()) {

        // Vamos recolocar esta linha na lista de não selecionados
        LinkedHashMap<String, String> newRow = new LinkedHashMap<>();

        // Vamos pegar todos os dados da linha
        for (int c = 0; c < this.headerCols.size(); c++) {
            newRow.put(
                this.headerCols.get(c),
                (String) this.tableModel.getValueAt(row, c)
            );
        }

        // Adiciona aos nao selecionados
        if (!this.data.contains(newRow)) {
            this.data.add(newRow);
        }
    }

    /**
     * MY PROBLEM ACTUALLY BEGINS HERE...
     */

    System.out.println("Begin (total selected): "+String.valueOf(this.table.getSelectedRowCount()));

    // Remove da tabela.
    while(this.table.getSelectedRow() != -1) {

        System.out.println("Removed item: "+String.valueOf(this.table.getSelectedRowCount()));

        this.tableModel.removeRow(this.table.getSelectedRow());
    }

    System.out.println("End (total selected): "+String.valueOf(this.table.getSelectedRowCount()));

Exception 例外

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Invalid index
at javax.swing.DefaultRowSorter.convertRowIndexToModel(DefaultRowSorter.java:514)
at javax.swing.JTable.convertRowIndexToModel(JTable.java:2642)
at javax.swing.JTable.getValueAt(JTable.java:2717)
at javax.swing.JTable.prepareRenderer(JTable.java:5706)
at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:683)
at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
at javax.swing.JComponent.paintComponent(JComponent.java:780)
at javax.swing.JComponent.paint(JComponent.java:1056)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5219)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:290)
at javax.swing.RepaintManager.paint(RepaintManager.java:1265)
at javax.swing.JComponent._paintImmediately(JComponent.java:5167)
at javax.swing.JComponent.paintImmediately(JComponent.java:4978)
at javax.swing.RepaintManager$4.run(RepaintManager.java:824)
at javax.swing.RepaintManager$4.run(RepaintManager.java:807)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:807)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:782)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:731)
at javax.swing.RepaintManager.access$1300(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1720)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Thank you very much, guys! 非常感谢你们!

You are incorrectly using a view-index to index the model. 您错误地使用了视图索引来索引模型。 The problems in your code: 您的代码中的问题:


  1. Your inner for loop should look like this: 您的内部for循环应如下所示:

int rowModelId = convertRowIndexToModel( row );
for (int c = 0; c < headerCols.size(); c++) {
    newRow.put(
        headerCols.get(c),
        (String) tableModel.getValueAt(rowModelId, c)
    );
}

  1. Deleting the rows should be done like this: 删除行应如下所示:

while(table.getSelectedRow() != -1) {
    int rowModelId = convertRowIndexToModel( table.getSelectedRow() );
    System.out.println("Removed item: "+String.valueOf(this.table.getSelectedRowCount()));
    tableModel.removeRow(rowModelId);
}

You can learn more about view-indexes vs model-indexes from the Documentation on JTable introduction at the top. 您可以从顶部的JTable介绍文档中了解有关视图索引与模型索引的更多信息。 Some relevant quotes: 一些相关的报价:

The JTable uses integers exclusively to refer to both the rows and the columns of the model that it displays. JTable仅使用整数来引用它显示的模型的行和列。 The JTable simply takes a tabular range of cells and uses getValueAt(int, int) to retrieve the values from the model during painting. JTable只是采用表格形式的单元格范围,并在绘制过程中使用getValueAt(int,int)从模型中检索值。 It is important to remember that the column and row indexes returned by various JTable methods are in terms of the JTable (the view) and are not necessarily the same indexes used by the model. 重要的是要记住,由各种JTable方法返回的列和行索引是根据JTable(视图)而言的,不一定与模型使用的索引相同。

By default, columns may be rearranged in the JTable so that the view's columns appear in a different order to the columns in the model. 默认情况下,列可能会在JTable中重新排列,以使视图的列以与模型中的列不同的顺序出现。 This does not affect the implementation of the model at all: when the columns are reordered, the JTable maintains the new order of the columns internally and converts its column indices before querying the model. 这一点根本不影响模型的实现:对列进行重新排序时,JTable在内部维护列的新顺序并在查询模型之前转换其列索引。

[...]The following shows how to convert coordinates from JTable to that of the underlying model: [...]下面显示了如何将JTable的坐标转换为基础模型的坐标:

int[] selection = table.getSelectedRows();
for (int i = 0; i < selection.length; i++) {
  selection[i] = table.convertRowIndexToModel(selection[i]);
}
// selection is now in terms of the underlying TableModel

I gave an answer to a similar question a while back that explains this difference between view and model . 不久前,我回答了一个类似的问题, 解释了视图和模型之间的这种区别 That case dealt with improper indexing of columns rather than rows, but the issue is comparable. 这种情况处理的是对列而不是行的不正确索引,但是这个问题是可比较的。

Javadoc is your friend! Javadoc是您的朋友!

All of JTables row based methods are in terms of the RowSorter, which is not necessarily the same as that of the underlying TableModel. 所有基于JTables行的方法都是基于RowSorter的,不一定与基础TableModel的相同。 For example, the selection is always in terms of JTable so that when using RowSorter you will need to convert using convertRowIndexToView or convertRowIndexToModel. 例如,选择始终是根据JTable进行的,因此,在使用RowSorter时,您将需要使用convertRowIndexToView或convertRowIndexToModel进行转换。

As per Java doc jTable.getSelectedRow() returns the first selected row index. 按照Java文档, jTable.getSelectedRow()返回第一个选定的行索引。 For the first loop everything is fine. 对于第一个循环,一切都很好。 But once you remove the row the rest of the rows will get new index after deletion of one row. 但是,一旦删除该行,其余一行将在删除一行后获得新索引。 So the row index now will be different for the rest of the rows remaining after deletion of one row. 因此,对于删除一行后剩余的其余行,现在行索引将有所不同。

The unsequenced debug report is because you have one row that is unselected in between the selected rows you are experimenting with. 未排序的调试报告是因为您在实验的所选行之间未选择一行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM