JTable
私のスイングスクリーンに1つ持ってください。画面の読み込み中に、このテーブル専用に作成された 1 つのテーブル モデルを設定しています。実行時にデータが変更された場合は、同じモデルを再作成し、 を使用して再度設定しobjJTable.setModel(objCustTableModel)
ます。
問題は、画面のロード時にロードされるテーブルモデルです。同じモデルオブジェクトが、クラスobjJTable.setModel(objCustTableModel)
から getColumnClass(int col) メソッドを呼び出した実行時の設定中に呼び出されます。CustTableModel
このオブジェクト呼び出しの後、新しいモデル オブジェクトが呼び出されます。同じコードを使用して別の新しいテーブル モデルを設定すると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 は、最初に内部的に呼び出されgetColumnClass
た関数に基づいてobjCustTableModel
、その後、objCustTableModel2
オブジェクトを使用します。に基づく通話を制限したいobjCustTableModel
。