Call previous behavior model JTable.setModel ()

Take one JTable on my swinging screen. While loading the screen, I set up one table created only for this table. And at runtime, if there are any data changes, I recreate the same model and set it again using objJTable.setModel(objCustTableModel) .

Now the problem is the model of the table, which is loaded during the loading of the screen, when calling objJTable.setModel(objCustTableModel) when calling the method called by the getColumnClass (int col) method from the CustTableModel class. After calling this object, my new model object is called. Again, if I set up another new table using the same code objJTable.setModel(objCustTableModel2) , the model invocation functions are called first from objCustTableModel and then objCustTableModel2 .

In short, the setModel() function first calls the previous model object, and then the current model object. How can I limit the call to the previous model object?

for instance

 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 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(); } } 

at this time, swing is first internally called the getColumnClass function based on objCustTableModel , and then using the objCustTableModel2 object. I want to limit the call, which is based on objCustTableModel .

+4
source share
3 answers

Starting with this, I did not see unexpected behavior with the getColumnClass() implementation shown below.

 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); } 

Note that JTable can call getColumnClass() at any time when it determines that the cell needs to be rendered. If necessary, you can use EventQueue.invokeLater() to schedule something to happen "after processing all pending events."

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

Addenda:

  • If getAutoCreateRowSorter() is true , setModel() attempts to restore a RowSorter created using the old model.

  • You can specify setAutoCreateRowSorter(true) after modifying the models as shown below, or expand your TableModel to update the model in place, as shown here .

  • Use ActionListener for JButton instead of MouseListener .

  • Use the TableCellEditor buttons for the buttons in the table, as shown here here and here .

code:

 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); } }); 
+4
source
  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()}); } 
+3
source

I had a similar problem before, since I called jTable.getValueAt (jTable.getSelectedRow (), col) in the jtable ListSelectionListener, and after changing the jtable model, it threw the wrong index, throwing an exception, after calling jTable.setModel (Model) after select the row, and it was solved by ensuring that the call to the value and the selected row graders - jTable.getValueAt (jTable.getSelectedRow (), col) - was not from the old events that they are still doing, by! event.getValueIsAdjusting () in the jtable ListSelectionListener, and I understood this notation on this issue that it should not have tried to call the value and the selected row graters when calling the old model in jtable set model calling - please if you have better knowledge if I'm wrong or not accurate - and this is an example of my previous problem, you can try to comment on the event.getValueIsAdjusting () event if you see the notation:

 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 } } 

this example should change the jTable6 model by selecting another switch in the switch group, using the setModel () method in the setTheDefaultJTable6Model () method. therefore, in this case, we are attached to the jtable model, not guaranteeing that it is not connected with previous events in which changes are still taking place, and we will get an exception after installing the jtable model in a new model.

0
source

All Articles