[英]Calling Previous Model Behavior of 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首先在內部調用getColumnClass
函數,在objCustTableModel
的基礎上, objCustTableModel
使用objCustTableModel2
對象。 我想限制基於objCustTableModel
。
從這個例子開始,我沒有看到下面顯示的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
來更新替代模型,如圖所示這里 。
使用ActionListener
for JButton
而不是MouseListener
。
碼:
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);
}
});
DefaultTableModel model ;
/** Creates new form DynRowAdd */
public DynRowAdd() {
initComponents();
model = new DefaultTableModel();
jTable1.setModel(model);
model.addColumn("Id");
model.addColumn("First Name");
model.addColumn("Last Name");
model.addColumn("Company Name");
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
model.addRow(new Object[]{jTextField1.getText(), jTextField2.getText(),jTextField3.getText(),jTextField4.getText()});
}
之前我遇到過類似的問題,因為我在jtable的ListSelectionListener中調用了jTable.getValueAt(jTable.getSelectedRow(),col),並且在更改jtable的模型之后,在調用jTable.setModel之后拋出了無效的索引,超出了綁定的異常(模型)在行選擇之后,它通過確保調用值和所選行getter來解決 - jTable.getValueAt(jTable.getSelectedRow(),col) - 不是來自舊事件,它們仍在制作中,在jtable的ListSelectionListener中的!event.getValueIsAdjusting(),我通過這個問題理解這個符號,它是在jtable的set模型調用中調用舊模型時不試圖調用值和選擇的行getter - 如果你有一個更好的知識,如果我錯了或不准確,請你糾正我 - 這是我之前問題的一個例子,你可以嘗試評論!event.getValueIsAdjusting()if條件,看看符號:
package testingsetmodel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class TestingSetModel extends javax.swing.JFrame implements ItemListener {
TestingSetModel() {
init();
}
private void init()
{
northPanel = new JPanel( ); // for adding jtable6
eastPanel = new JPanel( ); // for adding jtable7
southPanel = new JPanel( ); // for adding 2 jradiobuttons
first = new JRadioButton("1st");
second = new JRadioButton("2nd", true);
rg = new ButtonGroup( );
rg.add( first ) ; rg.add( second ) ;
first.addItemListener(this); second.addItemListener(this);
jScrollPane6 = new JScrollPane();
jScrollPane7 = new JScrollPane();
northPanel.add(jScrollPane6); eastPanel.add(jScrollPane7);
southPanel.add(first); southPanel.add(second);
jTable6 = new javax.swing.JTable(){
DefaultTableCellRenderer renderRight = new DefaultTableCellRenderer();
{ // initializer block
renderRight.setHorizontalAlignment(SwingConstants.RIGHT);
}
@Override
public TableCellRenderer getCellRenderer (int arg0, int arg1) {
return renderRight;
}
@Override
public boolean isCellEditable(int row, int col) {
switch (col) {
case 0:
return false;
default:
return true;
}
}
};
jTable6.setAutoCreateRowSorter(false);
jTable6.setFont(new java.awt.Font("Traditional Arabic", 0, 19));
jTable6.setEnabled(true);
jTable6.setRowHeight(25);
((DefaultTableCellRenderer)jTable6.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT);
jTable6.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jScrollPane6.setViewportView(jTable6);
jTable6.setSelectionBackground(new Color(0,100,255,7)); // cutomize selection color
jTable6.setSelectionForeground(Color.black);
jTable6.setRowSelectionAllowed(true);
setTheDefaultJTable6Model();
if(jTable6.getRowCount()>0)
{
for(int i = 0; i<jTable6.getRowCount(); i++)
{
if(jTable6.getValueAt(i,0).toString().equalsIgnoreCase("4"))
{
jTable6.setRowSelectionInterval(i, i);
jTable6.scrollRectToVisible(new Rectangle(jTable6.getCellRect(i, 0, true)));
}
}
}
jTable7 = new javax.swing.JTable(){
DefaultTableCellRenderer renderRight = new DefaultTableCellRenderer();
{ // initializer block
renderRight.setHorizontalAlignment(SwingConstants.RIGHT);
}
@Override
public TableCellRenderer getCellRenderer (int arg0, int arg1) {
return renderRight;
}
@Override
public boolean isCellEditable(int row, int col) {
switch (col) {
case 0:
return false;
default:
return true;
}
}
};
jTable7.setAutoCreateRowSorter(false);
jTable7.setFont(new java.awt.Font("Traditional Arabic", 0, 19));
jTable7.setEnabled(true);
jTable7.setRowHeight(25);
jTable7.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jScrollPane7.setViewportView(jTable7);
jTable7.setSelectionBackground(new Color(0,100,255,7)); // cutomize selection color for lite one for writting under selection
jTable7.setSelectionForeground(Color.black);
jTable7.setRowSelectionAllowed(true);
jTable6.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
@Override
public void valueChanged(ListSelectionEvent event) {
// try to comment the following if condition, and setting the model through changing the jradiobuttons
if(!event.getValueIsAdjusting() && jTable6.getSelectedRow() != -1 && jTable6.getSelectedRowCount() == 1)
{
DefaultTableModel clinicsSpecsJtableModel = new DefaultTableModel(); // the model
Object[] clinicsSpecsJtableColumnsNames = new Object[2]; // the four showable columns from the jtable model
clinicsSpecsJtableColumnsNames[0] = "name" ;
clinicsSpecsJtableColumnsNames[1] = "address" ;
clinicsSpecsJtableModel.setColumnIdentifiers(clinicsSpecsJtableColumnsNames);
Object[] clinicsSpecsJtableRowData = new Object[2];
ArrayList<String> clinicsNames = new ArrayList<>();
ArrayList<String> clinicsAddresses = new ArrayList<>();
clinicsNames.add("J34hp "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J34df "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J34as "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J34gh "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J45hj "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J56gr "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J34mn "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J56vr "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsNames.add("J45pi "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
clinicsAddresses.add("21 Tmk st");
clinicsAddresses.add("13 bcv st");
clinicsAddresses.add("67 rfb st");
clinicsAddresses.add("81 Tmk st");
clinicsAddresses.add("31 Tmk st");
clinicsAddresses.add("23 Jkl st");
clinicsAddresses.add("54 IUR st");
clinicsAddresses.add("51 Jkl st");
clinicsAddresses.add("71 rfb st");
for( int i=0 ; i<clinicsNames.size() ; i++ )
{
clinicsSpecsJtableRowData[0] = clinicsNames.get(i);
clinicsSpecsJtableRowData[1] = clinicsAddresses.get(i);
clinicsSpecsJtableModel.addRow(clinicsSpecsJtableRowData); // adding the row to the model
}
jTable7.setModel(clinicsSpecsJtableModel); // setting the model to the jtable
for (int column = 0; column < jTable7.getColumnCount(); column++)
{
TableColumn tableColumn = jTable7.getColumnModel().getColumn(column);
int preferredWidth = tableColumn.getMinWidth();
int maxWidth = tableColumn.getMaxWidth();
for (int row = 0; row < jTable7.getRowCount(); row++)
{
TableCellRenderer cellRenderer = jTable7.getCellRenderer(row, column);
Component c = jTable7.prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width + jTable7.getIntercellSpacing().width;
preferredWidth = Math.max(preferredWidth, width);
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth >= maxWidth)
{
preferredWidth = maxWidth;
break;
}
}
tableColumn.setPreferredWidth( preferredWidth );
}
jTable7.getTableHeader().setFont(new Font("Traditional Arabic", 0, 17)); // assure the column headers font and text size
((DefaultTableCellRenderer)jTable7.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT); // align right
jTable7.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // set single selection only enabled
jScrollPane7.setViewportView(jTable7); // draw jtable
}
}
});
Container cont = getContentPane();
cont.add(northPanel, BorderLayout.NORTH);
cont.add(eastPanel, BorderLayout.EAST);
cont.add(southPanel, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // to close the JFrame
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
EventQueue.invokeLater(() -> {
JFrame f = new TestingSetModel();
f.setSize(800, 600);
f.setVisible(true);
});
}
private javax.swing.JPanel northPanel, southPanel, eastPanel;
private javax.swing.JRadioButton first, second;
private javax.swing.ButtonGroup rg;
private javax.swing.JTable jTable6;
private javax.swing.JScrollPane jScrollPane6;
private javax.swing.JTable jTable7;
private javax.swing.JScrollPane jScrollPane7;
@Override
public void itemStateChanged(ItemEvent e) {
if(first.isSelected())
{
setTheDefaultJTable6Model();
removeJTable7Rows();
}else if(second.isSelected())
{
setTheCustomizedJTable6Model();
removeJTable7Rows();
}
}
private void removeJTable7Rows()
{
DefaultTableModel defaultModel = (DefaultTableModel) jTable7.getModel();
defaultModel.setRowCount(0);
}
private void setTheDefaultJTable6Model()
{
DefaultTableModel numbersJtableModel = new DefaultTableModel(); // the model
Object[] numbersJtableColumnsNames = new Object[1]; // the four showable columns from the jtable model
numbersJtableColumnsNames[0] = "number" ;
numbersJtableModel.setColumnIdentifiers(numbersJtableColumnsNames);
Object[] numbersJtableRowData = new Object[1];
ArrayList<String> numbers = new ArrayList<>();
numbers.add("1");
numbers.add("2");
numbers.add("3");
numbers.add("4");
numbers.add("5");
numbers.add("6");
for( int i=0 ; i<numbers.size() ; i++ ) // feeding array of object with numbers data
{
numbersJtableRowData[0] = numbers.get(i);
numbersJtableModel.addRow(numbersJtableRowData); // adding the row to the model
}
jTable6.setModel(numbersJtableModel); // setting the model to the jtable
for (int column = 0; column < jTable6.getColumnCount(); column++)
{
TableColumn tableColumn = jTable6.getColumnModel().getColumn(column);
int preferredWidth = tableColumn.getMinWidth();
int maxWidth = tableColumn.getMaxWidth();
for (int row = 0; row < jTable6.getRowCount(); row++)
{
TableCellRenderer cellRenderer = jTable6.getCellRenderer(row, column);
Component c = jTable6.prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width + jTable6.getIntercellSpacing().width;
preferredWidth = Math.max(preferredWidth, width);
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth >= maxWidth)
{
preferredWidth = maxWidth;
break;
}
}
tableColumn.setPreferredWidth( preferredWidth );
}
jTable6.getTableHeader().setFont(new Font("Traditional Arabic", 0, 17)); // assure the column headers font and text size
((DefaultTableCellRenderer)jTable6.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT); // align right
jTable6.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // set single selection only enabled
jScrollPane6.setViewportView(jTable6); // draw jtable
}
private void setTheCustomizedJTable6Model()
{
DefaultTableModel numbersJtableModel = new DefaultTableModel(); // the model
Object[] numbersJtableColumnsNames = new Object[1]; // the four showable columns from the jtable model
numbersJtableColumnsNames[0] = "number" ;
numbersJtableModel.setColumnIdentifiers(numbersJtableColumnsNames);
Object[] numbersJtableRowData = new Object[1];
ArrayList<String> numbers = new ArrayList<>();
numbers.add("10");
numbers.add("20");
numbers.add("30");
numbers.add("40");
numbers.add("50");
numbers.add("60");
for( int i=0 ; i<numbers.size() ; i++ ) // feeding array of object with numbers data
{
numbersJtableRowData[0] = numbers.get(i);
numbersJtableModel.addRow(numbersJtableRowData); // adding the row to the model
}
jTable6.setModel(numbersJtableModel); // setting the model to the jtable
for (int column = 0; column < jTable6.getColumnCount(); column++)
{
TableColumn tableColumn = jTable6.getColumnModel().getColumn(column);
int preferredWidth = tableColumn.getMinWidth();
int maxWidth = tableColumn.getMaxWidth();
for (int row = 0; row < jTable6.getRowCount(); row++)
{
TableCellRenderer cellRenderer = jTable6.getCellRenderer(row, column);
Component c = jTable6.prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width + jTable6.getIntercellSpacing().width;
preferredWidth = Math.max(preferredWidth, width);
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth >= maxWidth)
{
preferredWidth = maxWidth;
break;
}
}
tableColumn.setPreferredWidth( preferredWidth );
}
jTable6.getTableHeader().setFont(new Font("Traditional Arabic", 0, 17)); // assure the column headers font and text size
((DefaultTableCellRenderer)jTable6.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT); // align right
jTable6.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // set single selection only enabled
jScrollPane6.setViewportView(jTable6); // draw jtable
}
}
此示例應通過setTheDefaultJTable6Model()方法中的setModel()方法選擇單選按鈕組中的其他單選按鈕來更改jTable6的模型。 所以在這樣的情況下,我們與jtable模型有一定的聯系,而沒有確保它不是來自之前仍在進行更改的任何事件,我們會在將jtable的模型設置為新模型后得到異常
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.