【问题标题】:Last row always removed from DefaultTableModel, regardless of index无论索引如何,最后一行总是从 DefaultTableModel 中删除
【发布时间】:2017-01-20 20:23:02
【问题描述】:

当我尝试从 java 中的表中删除行时遇到一些问题。特别是,我使用DefaultTableModel,当我尝试删除一行时,使用removeRow(int row) 方法,无论row 是什么,最后一行都会被删除。例如,假设我们有六行。当调用removeRow(0)removeRow(2)removeRow(5) 时,总是删除最后一行。知道吗,为什么会这样?

谢谢

---更新

当按下 jtable 的特定单元格时,应删除相应的行。

    class TagsTableMA extends MouseAdapter {

    @Override
    public void mousePressed(MouseEvent e){
        Point p = e.getPoint();
        int row = tagsJT.rowAtPoint(p);
        int column = tagsJT.columnAtPoint(p);

        if (column == COLUMN_DELETE_TAG){
            DocDialog docDialog = new DocDialog(parentMainJF, 
                                                true, 
                                                null, 
                                                "Please confirm...", 
                                                "Are you sure you want to delete the \"" + 
                                                tagsJT.getValueAt(row, COLUMN_TAG_NAME) +
                                                "\" tag?",
                                                DocDialog.TYPE_YES_NO);
            docDialog.show();
            int answer = docDialog.getAnswer();

            if (answer == DocDialog.YES)                                                
                    model.removeRow(row);
        }
    }   
}

--- 更新 2 号 这是我的问题的一些代码。我删除了一些不相关的内容。

import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class MainJF extends JFrame {

public MainJF(){
    this.add(createTagsTable());
    setMinimumSize(new java.awt.Dimension(200,400));
}

 private JTable createTagsTable(){

    String[] columnNames = {"",          
                            "Tag",
                            "",
                            "",
                            ""};


    Object[][] data = new Object[10][columnNames.length];
    for (int i=0; i<data.length; i++){
        data[i][COLUMN_CHECK] = false;
        data[i][COLUMN_TAG_NAME] = "Tag " + i;
        data[i][COLUMN_TAG_ID] = i;
        data[i][COLUMN_EDIT_TAG] = "edit";
        data[i][COLUMN_DELETE_TAG] = "delete";
    }

    model = new TagsSelectionTableModel(columnNames, data);
    tagsJT = new JTable(model);

    tagsJT.setRowSelectionAllowed(true);
    tagsJT.addMouseListener(new TagsTableMA());

    return tagsJT;
}


class TagsSelectionTableModel extends DefaultTableModel{

    public TagsSelectionTableModel(String[] columnNames, Object[][] data){
        super(data, columnNames);
        this.columnNames = columnNames;
        this.data = data;
    }

    private String[] columnNames;
    private Object[][] data;


    @Override
    public Object getValueAt(int row, int col) { return data[row][col]; }
}

  class TagsTableMA extends MouseAdapter{

    @Override
    public void mousePressed(MouseEvent e){
        Point p = e.getPoint();
        int row = tagsJT.rowAtPoint(p);
        int column = tagsJT.columnAtPoint(p);

        if (column == COLUMN_DELETE_TAG){
            int irow = tagsJT.convertRowIndexToView(row);     
            model.removeRow(irow);
        }
    }
}


private JTable tagsJT;
private TagsSelectionTableModel model;   

private static int COLUMN_CHECK = 0;
private static int COLUMN_TAG_NAME = 1;
private static int COLUMN_TAG_ID = 2;
private static int COLUMN_EDIT_TAG = 3;
private static int COLUMN_DELETE_TAG = 4;


public static void main(String args[]) {
    new MainJF().setVisible(true);
}
}

【问题讨论】:

  • 你能显示你用来删除一行的代码吗?
  • 当然。我刚刚用一些代码更新了我的第一篇文章。

标签: java swing jtable row defaulttablemodel


【解决方案1】:

DefaultTableModelremoveRow(int)方法的代码,很明显它会去掉后面Vector对应索引处的行数组:

 public void removeRow(int row) {
    dataVector.removeElementAt(row);
    fireTableRowsDeleted(row, row);
} 

(来自 java 6)。

我能想到两种可能:

  1. 您已扩展 DefaultTableModel 并更改了此方法的实现。 (我怀疑是这样的——你可能会在你的帖子中承认这一点)

  2. 您有一个用于表格的自定义渲染器,它根据单元格的行索引绘制单元格数据。

【讨论】:

  • 还要考虑排序、过滤等,提到here
  • 感谢您的回复 1. 实际上,我已经扩展了DefaultTableModel,但我没有更改removeRow(int row) 的实现。 2. 不,我没有使用任何TableCellRenderer 在调试时我看到removeRow 占用的行是正确的,但由于某种原因,模型的最后一行总是被删除。
  • 看看你放入模型的数据会很有趣。
  • JLabels、图标、按钮、字符串和整数都包括在内。我覆盖了DefaultTableModelgetValueAt(int row, int col) 方法。这会导致问题吗?当我删除它时,它工作得很好,但其他一些功能不起作用,比如编辑。
  • 是的。 getValueAt 是这里的关键。这与我的第 2 点类似。如果您始终返回包含行索引的值,您将始终看到连续的值。
【解决方案2】:

columnAtPoint() 获得的row 位于视图 坐标中,而removeRow() 采用模型 坐标。引用自相关tutorial section

除非您查看的数据已通过排序、过滤或用户对列的操作重新排列,否则这种区别并不重要。

如果是这样,您将需要使用convertRowIndexToModel(),在Sorting and Filtering 末尾附近描述,它建议:

使用排序器时,请始终记住转换单元格坐标。

另外,请考虑使用ListSelectionListener 而不是MouseAdapter

附录:getValueAt() 的实现继续访问提供给构造函数的数组,而模型的数据实际上存储在父实现中。如果您确实需要对模型的数据结构进行更多控制,请扩展 AbstractTableModel,如图所示 here

import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

/** @see https://stackoverflow.com/a/11237205/230513 */
public class MainJF extends JFrame {

    private JTable tagsJT;
    private TagsSelectionTableModel model;
    private static int COLUMN_CHECK = 0;
    private static int COLUMN_TAG_NAME = 1;
    private static int COLUMN_TAG_ID = 2;
    private static int COLUMN_EDIT_TAG = 3;
    private static int COLUMN_DELETE_TAG = 4;

    public MainJF() {
        this.add(new JScrollPane(createTagsTable()));
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private JTable createTagsTable() {

        String[] columnNames = {"0", "Tag", "2", "3", "4"};

        Object[][] data = new Object[10][columnNames.length];
        for (int i = 0; i < data.length; i++) {
            data[i][COLUMN_CHECK] = false;
            data[i][COLUMN_TAG_NAME] = "Tag " + i;
            data[i][COLUMN_TAG_ID] = i;
            data[i][COLUMN_EDIT_TAG] = "edit";
            data[i][COLUMN_DELETE_TAG] = "delete";
        }
        model = new TagsSelectionTableModel(columnNames, data);
        tagsJT = new JTable(model);
        tagsJT.setRowSelectionAllowed(true);
        tagsJT.addMouseListener(new TagsTableMA());
        return tagsJT;
    }

    class TagsSelectionTableModel extends DefaultTableModel {

        public TagsSelectionTableModel(String[] columnNames, Object[][] data) {
            super(data, columnNames);
        }
    }

    class TagsTableMA extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            Point p = e.getPoint();
            int row = tagsJT.rowAtPoint(p);
            int col = tagsJT.columnAtPoint(p);
            if (col == COLUMN_DELETE_TAG) {
                model.removeRow(row);
            }
        }
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MainJF().setVisible(true);
            }
        });
    }
}

【讨论】:

  • 感谢您的回复。正如我所说,调试时我可以看到removeRow 占用的行是正确的,但由于某种原因,最后一行总是被删除。感谢您的建议。
  • 那么,没有排序、过滤、移位?您是通过invokeLater() 构建的吗?
  • 不,我不是。请参阅我的最后一条评论here。感谢您的帮助。
  • 好吧,我猜你可能在错误的模型上调用removeRow()sscce 可能会澄清。
  • 啊,您的示例没有从错误的模型中删除,它显示的是旧数据;以上。另请参阅Vector#removeElementAt()
猜你喜欢
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 2017-05-27
相关资源
最近更新 更多