TableModelListener and multiple column validation - java

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

Related

Adding a Button to JTable before creating the table

I'm working on Reflections and Swings for my project. Using reflections I need to get the information of a particular method, and populate a JTable based on its structure.
The table has the following feature:
Some columns will be named based on the parameter type present in the selected method.
Its the same structre for all the primitive data types(int,float,double,String,long,boolean), only the column names get Changed based on the data type.
The problem I face is when there is a User Defined object inside the method parameter.
In that scenario , I want a JButton instead of empty cell in the row (under that parameter type).
I tried learningTableCellRenderer and CellEditor but nothing helped me because all the tutorials i have seen are based on a Static data(rows and columns). In my case both rows and columns have to be generated dynamically and I need to create the JTable based on my data(dynamically).
I'm trying the following code:
rowData = new Object[1][colData.length];
rowData[0][0] = "";
rowData[0][colData.length - 1] = "";
int i = 1;
for (Class tempClass : paramType) {
if (tempClass.getSimpleName().equals("int")
//Primitives
|| tempClass.getSimpleName().equals("float")
|| tempClass.getSimpleName().equals("long")
|| tempClass.getSimpleName().equals("double")
|| tempClass.getSimpleName().equals("boolean")
|| tempClass.getSimpleName().equals("String")){
rowData[0][i] = "";
}
else{
//User Defined obj
rowData[0][i] = new JButton();
}
i++;
}
But the output i'm getting is something like this:
Kindly help me and provide me a hint or kind of tutorial so that i can proceed with this problem. I'm working on the swings for the first time.
The pictures you posted don't help me since the text to too small for me to read so I'm not sure what you are trying to demonstrate. Make sure the data is readable when you post a question is the data is in fact important to the question.
nothing helped me because all the tutorials i have seen are based on a Static data(rows and columns).
Maybe this example will help. It shows how to dynamically determine the renderer/editor for a cell based on the class of the data in the cell:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TablePropertyEditor extends JFrame
{
public TablePropertyEditor()
{
String[] columnNames = {"Type", "Value"};
Object[][] data =
{
{"String", "I'm a string"},
{"Date", new Date()},
{"Integer", new Integer(123)},
{"Double", new Double(123.45)},
{"Boolean", Boolean.TRUE}
};
JTable table = new JTable(data, columnNames)
{
private Class editingClass;
public TableCellRenderer getCellRenderer(int row, int column)
{
editingClass = null;
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == 1)
{
Class rowClass = getModel().getValueAt(row, modelColumn).getClass();
return getDefaultRenderer( rowClass );
}
else
return super.getCellRenderer(row, column);
}
public TableCellEditor getCellEditor(int row, int column)
{
editingClass = null;
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == 1)
{
editingClass = getModel().getValueAt(row, modelColumn).getClass();
return getDefaultEditor( editingClass );
}
else
return super.getCellEditor(row, column);
}
// This method is also invoked by the editor when the value in the editor
// component is saved in the TableModel. The class was saved when the
// editor was invoked so the proper class can be created.
public Class getColumnClass(int column)
{
return editingClass != null ? editingClass : super.getColumnClass(column);
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
}
public static void main(String[] args)
{
TablePropertyEditor frame = new TablePropertyEditor();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
Edit:
instead to get a Button, what should i keep
There is no default renderer/editor for a button, so you will need to store a custom object and create a custom renderer/editor.
Read the section from the Swing tutorial on Editors and Renderers for more information.
Then you have to tell the table about your custom objects with code like:
table.setDefaultRenderer(CustomObject.class, new CustomRenderer());
table.setDefaultEditor(CustomObject.class, new CustomRenderer());
You might be able to use the Table Button Column as the renderer/editor.

synchronize view of two JTable

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

How add status image in default jTable java Netbeans

I have a jtable functioning normally. The table lists tasks, and each task you an associated status.
I want every status is associated with an image.
So the image would appear in the table as show below.
------Code for jTable----------
DefaultTableModel tmSubTask = new DefaultTableModel(null, new String[]{"Status", "Priority", "Task", "SubTask", "Desc", "Prevision Begin", "Time", "Prevision Duration", "Prevision hour", "Begin", "Hour Begin","End Date" ,"End Hour", "Duration"});
List<SubTask> subTask;
ListSelectionModel lsmSubTask;
Connection conexao = null;
PreparedStatement pst= null;
ResultSet rs = null;
private void showSubTask(List<SubTask> subTask) {
while (tmSubTask.getRowCount() > 0) {
tmSubTask.removeRow(0);
}
if (subTask.size() == 0) {
JOptionPane.showMessageDialog(null, "showSubTask");
} else {
String[] line = new String[]{null, null, null};
for (int i = 0; i < SubTask.size(); i++) {
tmSubTask.addRow(linha);
tmSubTask.setValueAt(subTask.get(i).getStatus(), i, 0);
tmSubTask.setValueAt(subTask.get(i).getIdPriority(), i, 1);
tmSubTask.setValueAt(subTask.get(i).getIdTask(), i, 2);
tmSubTask.setValueAt(subTask.get(i).getIdSubTask(), i, 3);
tmSubTask.setValueAt(subTask.get(i).getDescSubTask(), i, 4);
tmSubTask.setValueAt(subTask.get(i).getDateBegin(), i, 5);
tmSubTask.setValueAt(subTask.get(i).getTerm(), i, 6);
tmSubTask.setValueAt(subTask.get(i).getDuration(), i, 7);
tmSubTask.setValueAt(subTask.get(i).gethourBeginP(), i, 8);
tmSubTask.setValueAt(subTask.get(i).getDateBegin(), i, 9);
tmSubTask.setValueAt(subTask.get(i).getHourBegin(), i, 10);
tmSubTask.setValueAt(subTask.get(i).getDateEnd(), i, 11);
tmSubTask.setValueAt(subTask.get(i).getHourEnd(), i, 12);
tmSubTask.setValueAt(subTask.get(i).getDuration(), i, 13);
}
}
}
---------------jTable--------------
---------------What I want---------
Imagine if Status like Delay in jTable show image red.
I honestly don't even know where to start.
I apologize if I did not make myself clear.
Thank all any help you can give me.
Greetings.
Any questions I will try to explain as best as possible.
Add an ImageIcon to the table and override the getColumnClass(...) method of the JTable to return Icon.class and the table will use an appropriate renderer to display the Icon. Something like:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableIcon extends JFrame
{
public TableIcon()
{
Icon aboutIcon = new ImageIcon("about16.gif");
Icon addIcon = new ImageIcon("add16.gif");
Icon copyIcon = new ImageIcon("copy16.gif");
String[] columnNames = {"Picture", "Description"};
Object[][] data =
{
{aboutIcon, "About"},
{addIcon, "Add"},
{copyIcon, "Copy"},
};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable( model )
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
new TableRowResizer(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumnAdjuster tca = new TableColumnAdjuster(table);
tca.adjustColumns();
}
public static void main(String[] args)
{
TableIcon frame = new TableIcon();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
}

Listening to many JTextFields and calculate value sum in a Row

I have an application that gets input from user;
it has 8 rows of JTextFields with 3 columns:
+-----------+-----------+-----------+
| Field 1-1 | Field 1-2 | Field 1-3 |
+-----------+-----------+-----------+
| Field 2-1 | Field 2-2 | Field 2-3 |
+-----------+-----------+-----------+
| Field 3-1 | Field 3-2 | Field 3-3 |
+-----------+-----------+-----------+
In each row while user changes first or second field the sum of new values must be written in third field.
For example when user changes Filed 1-1 & Field 1-2 sum of them must be calculated and shown in Field 1-3 and so on for other rows.
I wrote a Class that implements DocumentListener and and named it listenerClass & called .getDocument().addDocumentListener(new listenerClass) for all of JTextFields in column 1 & 2 ;
Now in listenerClass I need to know which JTextField called listenerClass to be able determine wich fields must be added and result must be written in which JTextField.
How Can I find out which JTextField called DocumentListener ?
Is there any better method to do this?
Thanks
You have two options here:
brute force: just one listener instance that will compute 8 sums and update 8 text fields
smart: pass to your listener class constructor 3 text fields and then instantiate a differente listener for each row
put a property with putClientProperty method on each JTextField. You can use that property as an id, and get it back inside the listener.
For example:
JTextField 1_1 = new JTextField();
1_1.putClientProperty("id", "1_1");
EDIT:
Sorry, I was forgetting that you don't have a reference to source object inside listener. SO it's better also do:
JTextField 1_1 = new JTextField();
1_1.getDocument.putProperty("source", 1_1);
the from inside the listener you can do:
public void insertUpdate(DocumentEvent documentEvent) {
//source
Object source = documentEvent.getDocument().getProperty("source");
if (source instanceof JTextField){
JTextField field = (JTextField)source;
String id = field.getClientProperty("id");
}
}
I asked a similar question some months ago: have a look here.
consider using JTable instead of plenty of JTextFields or JFormattedTextFields and listening by some of Listeners
from code
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableProcessing extends JFrame implements TableModelListener {
private static final long serialVersionUID = 1L;
private JTable table;
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);
model.addTableModelListener(this);
table = new JTable(model) {
private static final long serialVersionUID = 1L;
#Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
#Override
public boolean isCellEditable(int row, int column) {
int modelColumn = convertColumnIndexToModel(column);
return (modelColumn == 3) ? false : true;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
#Override
public void tableChanged(TableModelEvent e) {
System.out.println(e.getSource());
if (e.getType() == TableModelEvent.UPDATE) {
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 1 || column == 2) {
TableModel model = table.getModel();
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);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TableProcessing frame = new TableProcessing();
}
});
}
}
Use yourTextField.setName("Alice"), then in your DocumentListener implementation retrieve the name with with getName() and check for "Alice".
These methods belong to the java.awt.Component class. Every swing JComponent extends from it.

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

Categories