当重新排列列时,编辑JTable列将数据放在错误的列中

时间:2018-05-04 18:28:44

标签: java swing

我试图创造一个简单的" JTable使用TableModel绑定到ArrayList以扩展AbstractTableModel。我的目标是保留所有内置的JTable功能,允许单元格编辑,行排序和列重新排列。我在这里提供的示例完成所有这些......但是......在一定的操作序列下,当编辑单元格然后通过拖动列标题重新排列表格列,或者使用列标题按钮对表格进行排序时,内容最近编辑的单元格被复制到表格行的两列中。

我可以按如下方式重现问题:运行示例。双击或按F2编辑左上角单元格的内容,然后按ENTER键。将左侧列标题向右拖动到其相对位置。行的两个单元格的值都会更改以匹配所选单元格。同样,编辑左上角的单元格,然后按ENTER键。然后单击任一列标题以对表进行排序。排序根据需要完成,但刚刚编辑的单元格的内容将复制到行的另一列。如果按TAB或ESC终止编辑,则行为略有不同。但问题仍然发生在"权利"行动顺序。

我认为这个问题与我的TableModel.getValueAt和.setValueAt方法需要在TableModel列索引和View列索引之间进行转换有关,但是,就我而言,我无法弄清楚如何或在哪里进行转换。

任何帮助都将不胜感激。

package tableexample;

import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;


public final class TableExample extends JFrame {

        public List<REItem> REList;
        public JTable tblREList;


    public TableExample() {

        REList = new ArrayList<>();
        REList.add(new REItem("Template1", "Comment1"));
        REList.add(new REItem("Template2", "Comment2"));
        RETableModel retm = new RETableModel(REList);
        tblREList = new JTable(retm); 
        tblREList.setAutoCreateRowSorter(true);
        JScrollPane spREList = new JScrollPane(tblREList);
        this.add(spREList); //add the table to the frame
        this.setTitle("Table Example");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
        this.pack();
        this.setVisible(true);

    } // end TableExample constructor


    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            TableExample notUsed = new TableExample();
        });
    } //end main


    /**
     *      One item for the RETable
     */
    public final class REItem {
        String template;
        String comment;

        public REItem(String tmp, String cmt) {
            this.template = tmp;
            this.comment = cmt;
        }

        public String getTemplate() { return template; }

        public String getComment() { return comment; }

        public void setTemplate(String value) { this.template = value; }

        public void setComment(String value) { this.comment = value; }

    } // end class REItem


    public class RETableModel extends AbstractTableModel {

        private List<REItem> reList = new ArrayList();
        private final String[] columnNames = { "Template", "Comment" };

        public RETableModel(List<REItem> list){
             this.reList = list;
        }

        @Override
        public String getColumnName(int column){
             return columnNames[column];
        }

        @Override     
        public int getRowCount() {
            return reList.size();
        }

        @Override        
        public int getColumnCount() {
            return columnNames.length; 
        }

        @Override
        public Object getValueAt(int rowIndex, int column) {
            REItem rei = reList.get(rowIndex);
            switch (column) {
                case 0: 
                    return rei.getTemplate();
                case 1:
                    return rei.getComment();
               }
               return null; // default case
       }

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

       @Override
       public Class<?> getColumnClass(int column){
            switch (column){
                case 0:
                  return String.class;
                case 1:
                  return String.class;
            }
            return null; // default case
        }

     @Override
     public void setValueAt(Object value, int row, int column) {
            REItem rei = reList.get(row);
            switch (column) {
                case 0: 
                    rei.setTemplate(value.toString());
                case 1:
                    rei.setComment(value.toString());
               }
            // uncommenting the below often causes IndexOutOfBoundsException: Invalid range exception
            fireTableCellUpdated(row, column); 
     } // end setValueAt

    } // end RETableModel    

} // end class TableExample

2 个答案:

答案 0 :(得分:3)

switch语句执行匹配大小写后面的所有语句。这意味着,一旦满足条件,就会执行切换块中的所有代码。通过向每个案例添加break;可以避免这种情况。在您的示例中,当您设置模板时,还可以设置注释。

switch (column) {
    case 0:
        rei.setTemplate(value.toString());
        break;
    case 1:
        rei.setComment(value.toString());
        break;
   }

答案 1 :(得分:0)

这听起来像是Swing中的一个错误。示例代码中没有任何内容看起来错误。你的表模型没问题,如果你做错了什么就会出现在你的表中......你使用的是默认实现。

我能给出的唯一建议是尝试使用fireTableDataChanged()而不是fireTableCellUpdated(行,列)。没有尝试你的代码我认为你的数据可能很好(tablemodel的内容),但gui很困惑。

我没有发现其他人指出的setValueAt中缺少的中断。