编程语言
首页 > 编程语言> > java – 调用JTable.setModel()的先前模型行为

java – 调用JTable.setModel()的先前模型行为

作者:互联网

我的秋千屏幕上有一个JTable.在加载屏幕时,我正在设置一个仅为此表创建的表模型.
在运行时,如果有任何数据更改,我正在重新创建相同的模型,并再次使用objJTable.setModel(objCustTableModel)进行设置.

现在问题是在屏幕加载时加载的表模型,在运行时设置objJTable.setModel(objCustTableModel)时调用相同的模型对象,该方法从CustTableModel类调用getColumnClass(int col)方法.在此对象调用之后,我的新模型对象被调用.如果我再设置一个新的话
表模型,通过使用相同的代码objJTable.setModel(objCustTableModel2),模型调用的函数首先从objCustTableModel调用然后
objCustTableModel2.

简而言之,setModel()函数首先调用前一个模型对象然后调用当前模型对象.如何限制调用以前的模型对象?

例如

import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;


/**
 * Steps to reproduce issue.
 * 1. Run this program.
 * 2. There will be two rows in table. Delete all rows one by one.
 * 3. Now click on Add button and see the exception.
 * 
 * I come to know that this exception is because of table.setAutoCreateRowSorter(true); line, which is there in TestCustTableModel's constructor
 * If you comment this line, then issue got resolved.
 * But I want to apply sorting on columns so this line is required.
 */

public class TestCustTableModel extends JPanel{
    JTable table = new JTable();
    public TestCustTableModel() {

        Object[][] data = new Object[2][3];
        data[0][0] = "1";
        data[0][1] = "User1";
        data[0][2] = "Delete";

        data[1][0] = "2";
        data[1][1] = "User2";
        data[1][2] = "Delete";

        JButton addButton = new JButton("Add");
        addButton.addMouseListener(new AddListener());
        table.setModel(new CustModel(data));
        table.addMouseListener(new TableListener());

        /**#################################
         * Following line throws ArrayIndexOutOfBoundsException. Please comment or Uncomment following line and see the difference.
         */
        table.setAutoCreateRowSorter(true);


        table.getTableHeader().setCursor(new Cursor(Cursor.HAND_CURSOR));
        JScrollPane scrollPane = new JScrollPane(table);

        this.add(addButton);
        this.add(scrollPane);
    }


    class TableListener extends MouseAdapter {
        public void mouseClicked(MouseEvent evnt) {
            Point p = evnt.getPoint();
            if(table.columnAtPoint(p) == 2) {
                Object[][] data = null;
                if(table.getModel().getRowCount() == 2 && table.rowAtPoint(p) == 0) {
                    data = new Object[1][3];
                    data[0][0] = "2";
                    data[0][1] = "User2";
                    data[0][2] = "Delete";
                }else if(table.getModel().getRowCount() == 2 && table.rowAtPoint(p) == 1) {
                    data = new Object[1][3];
                    data[0][0] = "1";
                    data[0][1] = "User1";
                    data[0][2] = "Delete";
                }else {
                    data = new Object[0][];
                }
                table.setModel(new CustModel(data));
            }
        }
    }


    class AddListener extends MouseAdapter{

        @Override
        public void mouseClicked(MouseEvent evnt) {
            if(table.getModel().getRowCount() == 2) {
                return;
            }
            Object[][] data = new Object[table.getModel().getRowCount() + 1][3];
            for(int i = 0; i <= table.getModel().getRowCount(); i++) {
                data[i][0] = i;
                data[i][1] = "User" + i;
                data[i][2] = "Delete";
            }
            table.setModel(new CustModel(data));
        }

    }

    class CustModel extends AbstractTableModel {
        private String[] columnNames = {"ID", "NAME", "DELETE"};
        private Object[][] data = null;

        public CustModel(Object[][] data) {
            this.data = data;
        }
        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

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

        public Class getColumnClass(int col) {
            return getValueAt(0, col).getClass();
        }
    }

    private void display() {
        JFrame f = new JFrame("SwapTableModel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        TestCustTableModel obj = new TestCustTableModel();
        obj.display();
    }
}

此时swing首先在objCustTableModel的基础上内部调用getColumnClass函数,之后
使用objCustTableModel2对象.我想限制基于objCustTableModel的调用.

解决方法:

从这个example开始,我看到下面显示的getColumnClass()实现没有出现意外行为.

private Model() {
    final Object[] data = {this.toString()};
    this.model = new DefaultTableModel(data, 1){

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            System.out.println(data[0]);
            return super.getColumnClass(columnIndex);
        }
    };
    model.addRow(data);
}

请注意,JTable可以在确定单元格需要渲染时调用getColumnClass().如有必要,您可以使用EventQueue.invokeLater()来安排“在处理完所有待处理事件后发生”的事情.

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});

附加物:

>如果getAutoCreateRowSorter()为true,则setModel()尝试恢复使用旧模型创建的RowSorter.
>您可以在更改模型后指定setAutoCreateRowSorter(true),如下所示,或者扩展TableModel以更新模型,如图here所示.
>对JButton使用ActionListener而不是MouseListener.
>对表中的按钮使用TableCellEditor,如herehere所示.

码:

addButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        if (table.getModel().getRowCount() == 2) {
            return;
        }
        Object[][] data = new Object[table.getModel().getRowCount() + 1][5];
        table.setRowSorter(null);
        for (int i = 0; i <= table.getModel().getRowCount(); i++) {
            data[i][0] = i;
            data[i][6] = "User" + i;
            data[i][7] = "Delete";
        }
        table.setModel(new CustModel(data));
        table.setAutoCreateRowSorter(true);
    }
});

标签:java,swing,jtable,tablemodel
来源: https://codeday.me/bug/20190613/1229462.html