synchronize view of two JTable - java

I have two JTables one in main viewport and one in footer viewport, using JideScrollPane.
the problem is when the main JTable's view is customized, the footer JTable remains the
same, is there any way to synchronize their view?
thanks.

EDIT:
Here's a demo that will synch up the resizing of two tables that have similar columns. The idea is:
Create a custom TableColumnModelListener for each table's column model.
Upon resize, sync up the column widths. You'll have to disable the other listener temporarily, while this is happening.
For moving of columns, implement that logic in columnMoved(...) [left as an exercise]
This shows two-way synching:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class JTableResizeColumnsDemo implements Runnable
{
JTable table1, table2;
TableColumnModelListener columnListener1, columnListener2;
Map<JTable, TableColumnModelListener> map;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new JTableResizeColumnsDemo());
}
public void run()
{
Vector<String> names = new Vector<String>();
names.add("One");
names.add("Two");
names.add("Three");
table1 = new JTable(null, names);
table2 = new JTable(null, names);
columnListener1 = new ColumnChangeListener(table1, table2);
columnListener2 = new ColumnChangeListener(table2, table1);
table1.getColumnModel().addColumnModelListener(columnListener1);
table2.getColumnModel().addColumnModelListener(columnListener2);
map = new HashMap<JTable, TableColumnModelListener>();
map.put(table1, columnListener1);
map.put(table2, columnListener2);
JPanel p = new JPanel(new GridLayout(2,1));
p.add(new JScrollPane(table1));
p.add(new JScrollPane(table2));
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(p);
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class ColumnChangeListener implements TableColumnModelListener
{
JTable sourceTable;
JTable targetTable;
public ColumnChangeListener(JTable source, JTable target)
{
this.sourceTable = source;
this.targetTable = target;
}
public void columnAdded(TableColumnModelEvent e) {}
public void columnSelectionChanged(ListSelectionEvent e) {}
public void columnRemoved(TableColumnModelEvent e) {}
public void columnMoved(TableColumnModelEvent e) {}
public void columnMarginChanged(ChangeEvent e)
{
TableColumnModel sourceModel = sourceTable.getColumnModel();
TableColumnModel targetModel = targetTable.getColumnModel();
TableColumnModelListener listener = map.get(targetTable);
targetModel.removeColumnModelListener(listener);
for (int i = 0; i < sourceModel.getColumnCount(); i++)
{
targetModel.getColumn(i).setPreferredWidth(sourceModel.getColumn(i).getWidth());
}
targetModel.addColumnModelListener(listener);
}
}
}

You can apply an Observer pattern: the first JTable observes the second and vice versa. Then you add listners to both tables so that, when one is "customized", the other is notified. Basically, "being notified" consists in a method invocation that causes the update of the JTable.
In order to do that, you have two options:
You define a class Observer with a "register" method and a
"notify" method. When creating a JTable, you register it with the
Observer. Then, the listener you create and associate to each JTable
invoke the "notify" method of the observer, which informs all other
registered JTables of the change
You define a sort of "callback method" notify in the class that contains and declares the JTable. This "notify" method is invoked within the listner and updates the correct JTable. You can also create two methods: one for updating one JTable and one for the other JTable

Usually this is done by using the same model for different ui components. Sadly the JTable contains a bug that will cause problems when sharing the TableColumnModel.
But you can work around it using this JTable
class ShareableColumnModelTable extends JTable {
/**
* Fixes http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4816146 and
* more...
*
*/
#Override
public void columnMarginChanged(ChangeEvent e) {
if (isEditing()) {
removeEditor();
}
TableColumn resizingColumn = null;
if (tableHeader != null) {
resizingColumn = tableHeader.getResizingColumn();
}
if (resizingColumn != null) {
if (autoResizeMode == AUTO_RESIZE_OFF) {
resizingColumn.setPreferredWidth(resizingColumn.getWidth());
} else { // this else block is missing in jdk1.4 as compared to
// 1.3
TableColumnModel columnModel = getColumnModel();
/**
* Temporarily disconnects this column listener to prevent
* stackoverflows if the column model is shared between
* multiple JTables.
*/
columnModel.removeColumnModelListener(this);
try {
doLayout();
} finally {
columnModel.addColumnModelListener(this);
}
repaint();
return;
}
}
resizeAndRepaint();
}
}
With the ShareableColumnModelTableshowed above you can share one column model bettween multiple tables.
public static void main(String[] args) {
JFrame frame = new JFrame("Column Sync");
Container contentPane = frame.getContentPane();
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setResizeWeight(0.5d);
contentPane.add(splitPane);
JTable table1 = new ShareableColumnModelTable();
JTable table2 = new ShareableColumnModelTable();
TableColumnModel tableColumnModel = createTableColumnModel();
table1.setModel(createTableModel1());
table2.setModel(createTableModel2());
table1.setColumnModel(tableColumnModel);
table2.setColumnModel(tableColumnModel);
splitPane.setLeftComponent(new JScrollPane(table1));
splitPane.setRightComponent(new JScrollPane(table2));
showFrame(frame);
}
private static TableColumnModel createTableColumnModel() {
TableColumnModel tableColumnModel = new DefaultTableColumnModel();
TableColumn column1 = new TableColumn(0);
column1.setHeaderValue("1. column");
tableColumnModel.addColumn(column1);
TableColumn column2 = new TableColumn(1);
column2.setHeaderValue("2. column");
tableColumnModel.addColumn(column2);
return tableColumnModel;
}
private static TableModel createTableModel1() {
DefaultTableModel tableModel = new DefaultTableModel();
tableModel.setColumnCount(2);
tableModel.addRow(new Object[] { "a", "b" });
return tableModel;
}
private static TableModel createTableModel2() {
DefaultTableModel tableModel = new DefaultTableModel();
tableModel.setColumnCount(2);
tableModel.addRow(new Object[] { "c", "d" });
return tableModel;
}
private static void showFrame(JFrame frame) {
frame.setSize(240, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}

Related

empty TableModel after instantiating

Newbie seeking help please :-)
I am working on a little project to get familiar with Java desktop development and Database connectivity.
Attached code gives me an empty TableModel after instantiating therefore no data displayed in the JFrame.
Test class is instantiated from the menue of the main window with Test.showFrame();.
package ...
import ...
public class Test extends JPanel {
public Test() {
initializePanel();
}
private void initializePanel() {
// Creates an instance of TableModel
CategoryTableModel tableModel = new CategoryTableModel();
System.out.println(tableModel.getRowCount());
// Creates an instance of JTable with a TableModel
// as the constructor parameters.
JTable table = new JTable(tableModel);
table.setFillsViewportHeight(true);
JScrollPane scrollPane = new JScrollPane(table);
this.setPreferredSize(new Dimension(500, 200));
this.setLayout(new BorderLayout());
this.add(scrollPane, BorderLayout.CENTER);
}
public static void showFrame() {
JPanel panel = new Test();
panel.setOpaque(true);
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
class CategoryTableModel extends AbstractTableModel {
private List<Category> all = null;
private Iterator<Category> iterator = null;
private int tableRowCount;
private TableModel tableModel;
public CategoryTableModel(){
Vector tableData = new Vector();
// TableModel's column names
Vector<String> tableHeaders = new Vector<String>();
tableHeaders.add("Category");
// Database call
all = new ReadCategory().allCategories();
// TableModel's data
for(Object o : all) {
Vector<Object> row = new Vector<Object>();
all.forEach((n) -> row.add(new Category().getName()));
tableData.add(row);
System.out.println("row added");
}
tableRowCount = tableData.size();
tableModel = new DefaultTableModel(tableData, tableHeaders);
System.out.println(tableModel.getRowCount());
}
#Override
public int getRowCount() {
return 0;
}
#Override
public int getColumnCount() {
return 0;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return null;
}
}
}
Database call is fetching data via Hibernate and stores data in a .
Thanks for help.
In its most basic form a table model for a JTable defines the columns, the mapping of object to column and holds the data for the JTable to call upon. If we take your current table model and cut it down to fit this basic requirement we get the following.
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
public class CategoryTableModel extends AbstractTableModel {
private final List<Category> tableData = new ArrayList<>();
public void add(Category cat) {
tableData.add(cat);
fireTableDataChanged();
}
#Override
public String getColumnName(int column) {
String result = "";
if (column == 0) {
result = "Category Name";
}
return result;
}
#Override
public int getRowCount() {
return tableData.size();
}
#Override
public int getColumnCount() {
return 1;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return tableData.get(rowIndex).getName();
}
return null;
}
}
Notice that we do not define any data in the model itself. All we define is some storage for the data and the column name of the single column that we require.
I have added an add() method that allows you to add data to the model (you may wish to define remove etc. yourself). When you add or remove data from the model you must always let the JTable know that the data has changed by calling fireTableDataChanged() so that the table can redraw itself.
To use this table model you will need to do
CategoryTableModel model = new CategoryTableModel();
model.add(new Category());
JTable table = new JTable(model);
You can replace the model.add() with a loop that iterates over your data and adds it to the model.

How to add a button inside a table cell in java netbeans? (I am using the drag and drop method.)

I am trying to add a button inside a table cell. I am using the drag and drop method of netbeans since I know nothing about coding and will appreciate if you can teach me to code it. Thanks!
If you are using drag&drop in netbean for swing,
I highly advise you to touch the fundamental of swings , get your hands dirty so that you will know what is going on and how does the code work.
let me run through how you can achieve this. it will consist of 3 classes so that you will have a better understanding on what is going on and it practices oop too but of cause you can modify it to your preferred design pattern.
_main.java
public class _main extends JFrame{
private static final long serialVersionUID = 1L;
// Create new JFrame
_main(){
new JFrame("Main");
setLayout(new BorderLayout());
setSize(500,300);
add(new JLabel("Table Example ", SwingUtilities.CENTER) , BorderLayout.PAGE_START);
// ---------------- Call the method you have created in tableView.java ------------
add(new JScrollPane(new tableView(this).sampleTable()), BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args){
//Run Program
new _main();
}
}
tableView.java
public class tableView {
JFrame frame = new JFrame();
public tableView(JFrame frame) {
this.frame = frame;
}
//Create columnTitle & Table Model
String[] columnTitle = { "Data 1", "Data 2", "Data 3", "Buttons " };
DefaultTableModel model = new DefaultTableModel(columnTitle, 0);
public JTable sampleTable(){
JTable _dataTable = new JTable(model) {
#Override
public void updateUI() {
super.updateUI();
setRowHeight(34);
setAutoCreateRowSorter(true);
//------------ Placing button at your desired column ------------
TableColumn column;
column = getColumnModel().getColumn(3);
column.setCellRenderer(new tableModel(frame).new viewRenderer());
column.setCellEditor(new tableModel(frame).new ButtonsEditorView(this));
}
};
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment(JLabel.CENTER);
//-------- Adding data to your table row , use for loop for multiple data ---------
model.addRow(new Object[]{"1","2","3"});
return _dataTable;
}
}
tableModel.java
public class tableModel extends tableView{
public tableModel(JFrame frame) {
super(frame);
}
class viewButton extends JPanel {
public JButton viewbtnp = new JButton("View");
protected viewButton() {
setOpaque(true);
setFocusable(false);
add(viewbtnp);
}
}
class viewRenderer implements TableCellRenderer {
private final viewButton panel = new viewButton() {
#Override
public void updateUI() {
super.updateUI();
setName("Table.cellRenderer");
}
};
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
panel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
return panel;
}
}
class ViewAction extends AbstractAction {
private final JTable table;
protected ViewAction(JTable table) {
super("view");
this.table = table;
}
#Override
public void actionPerformed(ActionEvent e) {
//--------------------------- Create your own function on what you want the button to do when button is clicked -------------
System.out.println("Clicked ");
}
}
class ButtonsEditorView extends AbstractCellEditor implements TableCellEditor {
protected final viewButton panel = new viewButton();
protected final JTable table;
protected ButtonsEditorView(JTable table) {
super();
this.table = table;
panel.viewbtnp.setAction(new ViewAction(table));
}
#Override
public Component getTableCellEditorComponent(JTable tbl, Object value, boolean isSelected, int row,
int column) {
panel.setBackground(tbl.getSelectionBackground());
return panel;
}
#Override
public Object getCellEditorValue() {
return "";
}
}
}
Output
Hope it helps.
Cheers

Enabling auto resize of JTable only if it fit viewport

I need to create a JTable inside JScrollPane with resizeable columns (when user increase column width - horizontal scrollbar appears).
For this I have use table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);.
Also, when viewport is wide enough to contain entire table - columns should stretch to fill viewport width.
To accomplish this I have override getScrollableTracksViewportWidth() method of JTable class as follow:
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width < getParent().getWidth();
}
This approach works good, except one thing: when I first time try to resize column it return own width to start position. If I quickly resize column and release mouse table continue to work good.
So, what is the reason of such behavior? Why table try to resize even if getScrollableTracksViewportWidth() returns false? Or, maybe, you can propose better solution for implementing such resize mode?
Bellow is a simple working example of above problem:
import javax.swing.*;
public class TestTable {
private static Object[][] data = new Object[][] {
{ "a", "b", "c" },
{ "d", "e", "f" }
};
private static Object[] colNames = new Object[] { "1", "2", "3" };
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JTable table = new JTable(data, colNames) {
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width < getParent().getWidth();
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
}
});
}
}
It seemed like the default doLayout() logic wasn't working when you tried to increase the size of a column when the horizontal scrollbar wasn't visible, so I got rid of the default logic and just accepted the width of the column without attempting to adjust it.
import javax.swing.*;
import javax.swing.table.*;
public class TestTable {
private static Object[][] data = new Object[][] {
{ "a", "b", "c" },
{ "d", "e", "f" }
};
private static Object[] colNames = new Object[] { "1", "2", "3" };
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JTable table = new JTable(data, colNames)
{
#Override
public boolean getScrollableTracksViewportWidth()
{
return getPreferredSize().width < getParent().getWidth();
}
#Override
public void doLayout()
{
TableColumn resizingColumn = null;
if (tableHeader != null)
resizingColumn = tableHeader.getResizingColumn();
// Viewport size changed. May need to increase columns widths
if (resizingColumn == null)
{
setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
super.doLayout();
}
// Specific column resized. Reset preferred widths
else
{
TableColumnModel tcm = getColumnModel();
for (int i = 0; i < tcm.getColumnCount(); i++)
{
TableColumn tc = tcm.getColumn(i);
tc.setPreferredWidth( tc.getWidth() );
}
// Columns don't fill the viewport, invoke default layout
if (tcm.getTotalColumnWidth() < getParent().getWidth())
setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
super.doLayout();
}
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
}
});
}
}
Edited to use AUTO_RESIZE_ALL_COLUMNS.

JTable -> TableModeListener

I have this JTable having a DefaultTableModel as its model.
On the table I have several swing component, JComboBox and JCheckBox, set on a particular column via DefaultCellEditor and DefaultCellRenderer.
The TableModelListener was added to the table to capture changes on editable columns.
The rest of the columns will display details of the selected component, i.e. item code -> item price, item count, item classification,etc.
I have this problem wherein if the selectedItem of the JComboBox(itemCode) changes, the items of the other JComboBox(itemClassification) changes. But together with the change of the other JComboBox I need to display the item price on the same table. This change refires the valueChanged method which makes an infinite loop of valueChanged.
How can I get rid of the infinite loop thing?
One way is to check the update event to see what column the event is for and ignore columns that are automatically updated:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableProcessing extends JPanel implements TableModelListener
{
public TableProcessing()
{
String[] columnNames = {"Item", "Quantity", "Price", "Cost"};
Object[][] data =
{
{"Bread", new Integer(1), new Double(1.11), new Double(1.11)},
{"Milk", new Integer(1), new Double(2.22), new Double(2.22)},
{"Tea", new Integer(1), new Double(3.33), new Double(3.33)},
{"Cofee", new Integer(1), new Double(4.44), new Double(4.44)}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
#Override
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
// The Cost is not editable
#Override
public boolean isCellEditable(int row, int column)
{
return (column == 3) ? false : true;
}
};
model.addTableModelListener( this );
JTable table = new JTable( model );
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
String[] items = { "Bread", "Milk", "Tea", "Coffee" };
JComboBox<String> editor = new JComboBox<String>( items );
DefaultCellEditor dce = new DefaultCellEditor( editor );
table.getColumnModel().getColumn(0).setCellEditor(dce);
}
/*
* The cost is recalculated whenever the quantity or price is changed
*/
public void tableChanged(TableModelEvent e)
{
if (e.getType() == TableModelEvent.UPDATE)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 1 || column == 2)
{
TableModel model = (TableModel)e.getSource();
int quantity = ((Integer)model.getValueAt(row, 1)).intValue();
double price = ((Double)model.getValueAt(row, 2)).doubleValue();
Double value = new Double(quantity * price);
model.setValueAt(value, row, 3);
}
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Table Model Listener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TableProcessing());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
You could remove the listener when making changes from within the listener itself, and then re-add it when done with changes. Or you could give the Listener a boolean property that activates and deactivates the listener code, and set it appropriately from within the listener.
Actually...
I have also my answer.
I just get into the API of TableModelListener and I found the TableModelEvent.getColumn()
Thanks guys...

TableModelListener and multiple column validation

This is the first time for me to post here, so sorry if I made some mistake.
I am working on a JTable which column data have to verify some parameters, for example:
Column 3 values > 30
Column 4 values > 10
Column 5 values > 4
Also the first 2 columns are filled "automatically", putting 0s in the rest of the columns.
If that data is correct, in the Column 5 I would show an image of a tick, otherwise, I would show an image of a warning.
For verifying this I use the following code
ImageIcon accept = new javax.swing.ImageIcon(getClass().getResource("/resources/accept.png"));
ImageIcon deny = new javax.swing.ImageIcon(getClass().getResource("/resources/exclamation.png"));
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
double d1 = Double.valueOf(jTable.getValueAt(row, 2).toString());
double d2 = Double.valueOf(jT.getValueAt(row, 3).toString());
double d3 = Double.valueOf(jT.getValueAt(row, 4).toString());
if(d1>MAX_A||d2>MAX_B||d3>MAX_C){
jTable.setValueAt(deny, row, 5);
}
else{
jTable.setValueAt(accept, row, 5);
}
}
The problem of this code is that returns a Stack Overflow, and I don't know how to handle this.
Is there any other way to implement some verifier on a table that implies multiple cells?
Thanks in advance.
The problem of this code is that
returns a Stack Overflow, and I don't
know how to handle this.
The problem is that your code sets a value in the model listener so another tableChanged event is generated. Your code should be something like:
if (e.getColumn() != 5)
// do your code
I don't see a problem using a TableModelListener to dynamically set the value of a column based on data in another column. Here is a simple example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableProcessing extends JPanel implements TableModelListener
{
public TableProcessing()
{
String[] columnNames = {"Item", "Quantity", "Price", "Cost"};
Object[][] data =
{
{"Bread", new Integer(1), new Double(1.11), new Double(1.11)},
{"Milk", new Integer(1), new Double(2.22), new Double(2.22)},
{"Tea", new Integer(1), new Double(3.33), new Double(3.33)},
{"Cofee", new Integer(1), new Double(4.44), new Double(4.44)}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
#Override
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
// The Cost is not editable
#Override
public boolean isCellEditable(int row, int column)
{
return (column == 3) ? false : true;
}
};
model.addTableModelListener( this );
JTable table = new JTable( model );
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
String[] items = { "Bread", "Milk", "Tea", "Coffee" };
JComboBox<String> editor = new JComboBox<String>( items );
DefaultCellEditor dce = new DefaultCellEditor( editor );
table.getColumnModel().getColumn(0).setCellEditor(dce);
}
/*
* The cost is recalculated whenever the quantity or price is changed
*/
public void tableChanged(TableModelEvent e)
{
if (e.getType() == TableModelEvent.UPDATE)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 1 || column == 2)
{
TableModel model = (TableModel)e.getSource();
int quantity = ((Integer)model.getValueAt(row, 1)).intValue();
double price = ((Double)model.getValueAt(row, 2)).doubleValue();
Double value = new Double(quantity * price);
model.setValueAt(value, row, 3);
}
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Table Model Listener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TableProcessing());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
You probably get your error because of getFirstRow call. I think it's a bad idea to validate table structure in JTable.tableChanged - how do you know that the table was fully filled and ready for validation? I would suggest filling the whole table first, then invokation of validation. Maybe there would be also a good idea to use separate table to display validation results

Categories