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,如here和here所示.
码:
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