使用AbstractTableModel从JTable中选择表行时出错

时间:2012-04-01 23:48:15

标签: java swing jtable abstracttablemodel

我有一个类型为module的ArrayList,每个模块都有一个Assignments的arraylist。我编写了下面的TableModel,但是当在表中选择了某些东西时,我遇到了问题,导致我的ArrayLists超出范围。这是我的桌子模型:

public class AssignmentsTableModel extends AbstractTableModel {
private ArrayList<Module> modules;
private static final String[] COLUMN_NAMES = {"Module Identifier", "Module Name", "Assignment Title", "Author", "Date Set", "Date Due", "Weighting"};

private int moduleID;
private int assignmentID;
private Module module;
private int totalNumberAssignments;

public AssignmentsTableModel(ArrayList<Module> modules) {
    moduleID = 0;
    assignmentID = 0;
    this.modules = modules;
    module = modules.get(moduleID);
    totalNumberAssignments = getRowCount();
}

public AssignmentsTableModel(Module module) {
    modules = new ArrayList<Module>();
    modules.add(module);
}

@Override
public int getRowCount() {
    int rowCount = 0;
    for(Module mod : modules){
        rowCount += mod.getAssignments().size();
    }
    return rowCount;
}

@Override
public int getColumnCount() {
    return COLUMN_NAMES.length;  //To change body of implemented methods use File | Settings | File Templates.
}

@Override
public Object getValueAt(int row, int column) {
    if(column%getColumnCount() == 0 && getRowCount() <= totalNumberAssignments){
        if(isAtLastAssignment(row, moduleID)){
            assignmentID = 0;
            moduleID += 1;
        }
    }

    module = modules.get(moduleID);
    ArrayList<Assignment> assignments = module.getAssignments();

    Assignment assignment = assignments.get(assignmentID);

    switch (column){
        case 0: return module.getIdentifier();
        case 1: return module.getTitle();
        case 2: return assignment.getTitle();
        case 3: return assignment.getAuthor();
        case 4: return assignment.getSet();
        case 5: return assignment.getDue();
        case 6: return assignment.getWeighting();
        default: return null;
    }


}

public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
}

public boolean isAtLastAssignment(int row, int moduleID){
    boolean atLast = false;
    ArrayList<Assignment> assignments = modules.get(moduleID).getAssignments();
    if(moduleID == 0){
        if(row == assignments.size()){
            atLast = true;
        }
    } else {
        int assignmentsSize = assignments.size() + getCurrentRowNumber(moduleID);
        if(row == assignmentsSize){
            atLast = true;
        }
    }

    return atLast;
}

public int getCurrentRowNumber(int moduleID){
    int rowNumber = 0;

    for(int i = 0; i < moduleID; i++){
        rowNumber = modules.get(i).getAssignments().size()-1;
    }

    return rowNumber;
}
}

正如您所看到的,我将moduleID存储为全局变量,这在第一次启动时很好,但是一旦选择了某些内容,它就会使用最后的值。我还能做些什么来阻止这种情况发生?

2 个答案:

答案 0 :(得分:5)

TableModel方法getValueAt()每次想要获取单元格的值时都会被表格渲染器调用,以便它可以渲染它。它(直接或可靠地)与您单击表格行并让表格将该行标记为已选择相关。

换句话说,您不希望因调用getValueAt()方法而改变表模型的状态。

如果您的getValueAt()方法使用该行作为数组的索引,那将是最简单的。但是,看起来每个模块的行数可变。在这种情况下,如果您无法通过算法生成正确的索引,则可以在构造函数中“展平”一次数据,并简化查找代码。

也就是说,您的表模型包含:

private List<RowData> rowData

和包含行数据的内部类:

private static class RowData
{
  private Moddule;
  private Assignment assignment;

  ...
}

在你的构造函数中:

public AssignmentsTableModel(List<Module> modules)
{
  this.rowData = new ArrayList<Module>();

  for (Module module : modules)
  {
    for (Assignment assignment : module.getAssignments())
    {
      rowData.add(new RowData(module, assignment));
    }
  }
}

这简化了您的getValueAt()方法:

@Override
public Object getValueAt(int row, int column) {
    final RowData row = this.rowData.get(row);

    switch (column){
        case 0: return row.getModule().getIdentifier();
        case 1: return row.getModule().getTitle();
        case 2: return row.getAssignment().getTitle();
        case 3: return row.getAssignment().Author();
        case 4: return row.getAssignment().getSet();
        case 5: return row.getAssignment().getDue();
        case 6: return row.getAssignment().getWeighting();
        default: return null;
    }
}

答案 1 :(得分:1)

  • 选择基本上与TableModel没有关系,也许还有其他问题,或者你没有在这里发布的其他代码或方法,

  • 基本成功我错过了从AbstractTableModelModel添加/修改/删除数据,行或列所需的View的另一种方法亦然)

  • 使用DefaultTableModel,也许没有理由使用AbstractTableModel

  • 您可以比较基本AbstractTableModel所需的方法,使用直接在API中实现的Object[][]Vector<Vector<Object>>,而不是另一个数组或哈希的类型,

  • 请阅读tur How JTable works

修改

@Dean写道:

that I can't see another way around but when an update in the table happens

这就是为什么setXxxMethods(里面有fireXxxXxx方法)存在的原因,关于JTable的Oracle教程提到了更多次的