Interacting with JTable which is rapidly updated with new rows - java

Brief description of a problem.
Assume we have JTable and user interacting with it in some way. TableModel of this table is constantly changing. How to ensure that when user tries to get some info from the table by referencing some constant column and currently selected row (by its rowIndex he got from JTable), he will not get into situation when TableModel is changed and his rowIndex obtained from JTable is no longer corresponding to same value in TableModel.
Following is initial question which explains problem in more detail:
Consider following situation:
There is JTable which shows user info about currently running requests in some system
When new request enters system, new row is being added to the table
user can interact with table by right-clicking on a row (single row selection model is used in table) and choosing option from the menu (like: abort, postpone, retry, etc.)
there is separate class which implements ActionListener interface (listens to the table) and handles all user interactions
When user does some action on the table this class checks currently selected row and assigns some values for user's action (basically it takes index of selected row and then calls tableModel.getValueAt(indexOfSelectedRow, someValuableDataColumnIndex))
Now consider scenario when system is under stress test and requests are being submitted constantly with big frequency. This, in my case, leads to a bug, when sometimes class which handles user's actions gets wrong info from table model (action was called on one row, but action is done for another, usually next one). I believe this happens because during some inits in action handling class table model is changed because of new request accepted.
Question is, how to fix this. I am thinking about two approaches:
use something like invokeAndWait() for initialization in my user actions' handling class (don't like this idea, because imo it will lead to other unpredictable bugs)
creating separate listener class which will listen to user selections in the table and store data from selected row as soon as it was selected separately from TableModel. This way actions handling class will take data not from table model which is being changed, but from selected row, which is constant during the described scenario. (not sure this idea will work)
Please, comment on my ideas, and suggest yours.
I am sorry for absence of any code here, but original code will take way too much space, and model example isn't something what can be done easily here.

I don't think inserting rows in a table changes the selection, so as long as you are updating the TableModel on the EDT, the selected row is still same when the user shows the popup and chooses and action from the popup.
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class TestJTableInsert {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final DefaultTableModel model = new DefaultTableModel(0, 1);
new Timer(500, new ActionListener() {
private final Random random = new Random();
private int data = 1;
#Override
public void actionPerformed(ActionEvent e) {
model.insertRow(random.nextInt(model.getRowCount() + 1),
new Object[] { data++ });
}
}).start();
final JTable table = new JTable(model);
JPopupMenu popup = new JPopupMenu();
popup.add(new AbstractAction("Which row is this?") {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(table,
"This is row " + table.getValueAt(table.getSelectedRow(), 0));
}
});
table.setComponentPopupMenu(popup);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

model example isn't something what can be done easily here.
Here's a starter to demonstrate that the selection is kept constant (in the sense that it always points to the same "real" row:
final DefaultTableModel model = new DefaultTableModel(0, 1);
for (int i = 0; i < 50; i++) {
model.addRow(new Object[] {i});
};
final JXTable table = new JXTable(model);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setRowSelectionInterval(25, 25);
Action l = new AbstractAction("random insert") {
Random random = new Random();
#Override
public void actionPerformed(ActionEvent e) {
int row = random.nextInt(model.getRowCount());
model.insertRow(row, new Object[] {"inserted at: " + row});
table.scrollRowToVisible(table.getSelectedRow());
}
};
new Timer(100, l).start();

Related

How to refresh JTable with always-changing tableModel?

2015.5.5 22:11 updated. I found that, when I create a sorter and call setRowSorter() method in the MyTable's construction, afterwards, it
will keep the original line number(in which the data still refresh
correctly but not easy to discover)even though the dataModel inside is
already changed many times which can be proven as
printf(getModel().getRowCount()). What's more,
MyTable.getAutoCreateRowSorter() always return true. I must explicitly
call setAutoCreateRowSorter(true) to fix the issue it if I called
setRowSorter(). I am happy but this is still wierd.
[2015.5.5 6:19 updated] I have found a way to access: make a "setRow" with the combination of insertRow() and removeRow() and everytime I
update, I setrRow all the rows in the table. It reflect immediately in
the UI. BUT there will be a series of error begin with "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Invalid index" and I guess it's about some kiind of swing thread problem because I can see "RepaintManager" or "paint" in the error. It occurs especially when I move the scrollbar when it's running.(but it still occur if I don't move it)
I have a JTable in a JScrollPane in a JFrame. I initial a MyTableModel with a data and use it to Create a JTable.Like this
MyTableModel extends DefaultTableModel{
Data data;
//object
MyTableModel (Data a){
data = a;
// do something to initial the table model,like build object[][] and add rows.
}
}
class main{
MyTableModel tm = new MyTableModel(data);
Jtable table = new JTable(tm);
JScrollpane jsp = new JScrollpane(table);
JFrame window = new JFrame();
window.getxxxpane().add(jsp);
}
So, as my data is always changing/updating and the changed row is plural and impossible to caculate.
while(true){
data.change();
refreshing the table to display the data immediately;
}
my idea is to simply build a new MyTableModel object and set it as the table's model like:
table.setModel(new MyTableModel(data)); //data had been changed.
which doesn't work.
and I tried this:
tm = MyTableModel(data);
tm.fireTableDataChanged();
which doesn't work either.
and the combination as well:
MyTableModol nm = new MyTableModel(data); //data had been changed
table.setModel(nm);
nm.fireTableDataChanged();
Could someone please give me some clue to change the TableModel object in an unchangable Jtable and update everytime.I dont want to change the tableModel Object because the calculation is huge, instead ,i Want to always create a new object with the construction method's parameter(changed data).
the most worst method is to remove the JScrollpane and rebuild one table/tablemodel/jscrollpane and re-add it, in which I have to call window.setVisible(true). window.repait() doesn't work,either,unless I move it.
I create a space-wasting but runnable program for demostration ,which most of them are nonsense.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Formatter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
class TM extends DefaultTableModel {
int[] inside;
static String[] columnNames = { "Hellium", "Radon",
};
TM(int[] data) {
super(columnNames, 0);
this.inside = data;
update();
}
void update() {
Object[][] data = new Object[2][columnNames.length];
for (int i = 0; i < 2; ++i) {
data[i][0] = inside[0];
data[i][1] = inside[1];
// setValueAt(aValue, row, column);
addRow(data[i]);
}
fireTableDataChanged();
}
}
class idkName {
TM tm;
JButton jb, jb2;
int data[] = { 1, 2 };
int data2[] = { 9, 10 };
JTable table;
JScrollPane jsp;
JFrame twindow;
idkName() {
JFrame window = new JFrame();
window.setSize(400, 400);
window.setLayout(new BorderLayout());
jb = new JButton("show");
jb2 = new JButton("change model");
window.add(jb, BorderLayout.EAST);
window.add(jb2, BorderLayout.WEST);
twindow = new JFrame();
jb.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
tm = new TM(data);
table = new JTable(tm);
jsp = new JScrollPane(table);
twindow.getContentPane().add(jsp);
twindow.setSize(500, 500);
twindow.setVisible(true);
}
});
window.setVisible(true);
jb2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
// tm = new TM(data2);
tm = new TM(data2);
System.out.println(""+tm.getValueAt(0,0));
tm.fireTableDataChanged();
twindow.setVisible(true);
}
});
}
}
public class main2 {
TM tm;
public static void main(String[] args) {
idkName i = new idkName();
}
}
If you're going to extend DefaultTableModel, then when the data is changed, you need to update it in DefaultTableModel's internal representation using the setValueAt or setDataVector methods. If you have extensive changes (which it sounds like you do), use the setDataVector method to change all the cells and the table structure at once. Your example code looks like it's missing some updates because it's not pushing the new values in to the DefaultTableModel's data vectors.
But since you have a lot of updates, you're probably better off avoiding DefaultTableModel and just extending AbstractTableModel, using your own custom data storage, and calling the appropriate fireXxx() methods whenever your data changes. This will probably be more efficient in terms of both data conversion and number of events raised.
And then make sure all the event and value change work is done on the AWT event thread, using SwingWorkers or other threading support.

JXTable not refreshed upon button click

I have a JFrame which holds a JXTable (from SwingX dependency) and a JButton.
Once I click the JButton the table should get updated each time. In my case it gets updated only at the first time. Other events also get triggered on the button click (which happens each time I click the button). Only the table is not refreshed with the new rows added.
I am using DeafultTableModel and have tried (explicit trigger) all suggested methods like repaint, fireTableDataChanged etc.
Can someone please help?
EDIT-1 (code snippet added): -
// the actions will take place when VALIDATE button is clicked
validateButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent ae) {
if (evCheckbox1.isSelected() || !list.isSelectionEmpty()) {
try {
// store the validation errors for future use
List<List<String>> validationErrors = validateSheet(Driver.this.fileLocation, list
.getSelectedValuesList(), regulatorTypeCB.getSelectedItem().toString(), sheetTypeCB
.getSelectedItem().toString());
// creates the validation error overview to be added to roTable
Map<String, Integer> tmpMap = getValidationErrorsOverview(validationErrors);
System.out.println(tmpMap);
// create the report overview table
String[] columnNames = {"SHEET_NAME", "VALIDATION_NAME", "#"};
DefaultTableModel tmodel = new DefaultTableModel(0, 0);
tmodel.setColumnIdentifiers(columnNames);
JXTable roTable = new JXTable();
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
roTable.addHighlighter(HighlighterFactory.createSimpleStriping());
List<String> tlist = new ArrayList<String>();
JScrollPane scrPane = new JScrollPane(roTable);
scrPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
overviewPanel.add(scrPane);
// create a list from the validation error overview map to insert as a row in table
for (Map.Entry<String, Integer> entry : tmpMap.entrySet()) {
tlist.add(entry.getKey().split(":")[0]);
tlist.add(entry.getKey().split(":")[1]);
tlist.add(String.valueOf(entry.getValue()));
}
// add rows in table
for (int i = 0; i < tmpMap.size(); i++) {
tmodel.addRow(new Object[] {tlist.get((i * 3) + 0), tlist.get((i * 3) + 1),
tlist.get((i * 3) + 2)});
}
FileUtils.writeStringToFile(logFile, "\n" + new Date().toString() + "\n", true);
roTable.setModel(tmodel);
roTable.repaint();
// frame refresh
Driver.this.frame.revalidate();
Driver.this.frame.repaint();
// open the log file in notepad.exe
ProcessBuilder pb = new ProcessBuilder("Notepad.exe", "verifier.log");
pb.start();
} catch (BiffException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
There are some conceptual mistakes in the lines below:
String[] columnNames = {"SHEET_NAME", "VALIDATION_NAME", "#"};
DefaultTableModel tmodel = new DefaultTableModel(0, 0);
tmodel.setColumnIdentifiers(columnNames);
JXTable roTable = new JXTable();
...
JScrollPane scrPane = new JScrollPane(roTable);
...
overviewPanel.add(scrPane);
1) Don't create a new JXTable when you press the button but work with the table model instead either by clearing the current table model and adding rows to it or directly by setting a new one. For example:
String[] columnNames = {"SHEET_NAME", "VALIDATION_NAME", "#"};
DefaultTableModel tmodel = new DefaultTableModel(0, 0);
tmodel.setColumnIdentifiers(columnNames);
yourTable.setModel(tmodel);
2) These lines suggests that overviewPanel has already been displayed by the time you are trying to add the new table by clicking the button, thus invalidating the components hierarchy and in consequence you have to revalidate and repaint the panel like this:
overviewPanel.add(scrPane);
overviewPanel.revalidate();
overviewPanel.repaint();
However while we can add components dynamically in Swing we tipically place all our components before the top-level container (window) is made visible. Thus the approach described in point 1 is highly preferable over this one and I'm adding this point just for completeness.
3) Be aware that time consuming tasks such as database calls or IO operations may block the Event Dispatch Thread (EDT) causing the GUI become unresponsive. The EDT is a single and special thread where Swing components creation and update take place. To avoid block this thread consider use a SwingWorker to perform heavy tasks in a background thread and update Swing components in the EDT. See more in Concurrency in Swing lesson.
Update
Please consider the following example illustrating point 1:
The table is created and placed once before making the top-level container (window) visible.
Both actions work with the table model: one of them sets a new table model and the other one clear and re-fill the current table model.
Here is the code. Hope it helps!
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import org.jdesktop.swingx.JXTable;
public class Demo {
private void createAndShowGUI() {
final JXTable table = new JXTable(5, 6);
table.setPreferredScrollableViewportSize(new Dimension(500, 200));
Action resetModelAction = new AbstractAction("Set a new model") {
#Override
public void actionPerformed(ActionEvent e) {
Random random = new Random(System.currentTimeMillis());
DefaultTableModel model = new DefaultTableModel(0, 6);
for (int i = 0; i < model.getColumnCount(); i++) {
model.addRow(new Object[]{
random.nextInt(),
random.nextInt(),
random.nextInt(),
random.nextInt(),
random.nextInt(),
random.nextInt()
});
}
table.setModel(model);
}
};
Action clearAndFillModelAction = new AbstractAction("Clear and fill model") {
#Override
public void actionPerformed(ActionEvent e) {
Random random = new Random(System.currentTimeMillis());
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.setRowCount(0); // clear the model
for (int i = 0; i < model.getColumnCount(); i++) {
model.addRow(new Object[]{
random.nextInt(),
random.nextInt(),
random.nextInt(),
random.nextInt(),
random.nextInt(),
random.nextInt()
});
}
}
};
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton(resetModelAction));
buttonsPanel.add(new JButton(clearAndFillModelAction));
JPanel content = new JPanel(new BorderLayout(8,8));
content.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));
content.add(new JScrollPane(table));
content.add(buttonsPanel, BorderLayout.PAGE_END);
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(content);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}

Refresh table's row (Not row's value) on frame?

Sorry for being so amateur, I created a 'button' on a frame so that when we click the button for the first time, A ROW will be inserted on the frame. But ALL I WANT is that when I click the button THE SECOND TIME, the ROW IS REFRESHED (Not creating a new row!), I know that '.addRow(new Object[] { "", "", ""});' is the cause , because the object is created every time I click the button, so how could I possibly modify the code? Thanks for your attention.
*My weak brain said that if only I can empty 'model' object (or destroying the object, something like that), then I would find the solution, but how I could possibly empty/destroy that 'model' object?
import javax.swing.*;
import java.awt.event.*;
import javax.swing.table.DefaultTableModel;
public class MyTable extends JFrame {
private JTable table;
private DefaultTableModel model;
private JScrollPane scroll;
private JButton createRow;
private String headers[] = {"a", "b", "c"};
public MyTable() {
createRow = new JButton("Create Row");
model = new DefaultTableModel();
model.setColumnIdentifiers(headers);
table = new JTable();
table.setModel(model);
scroll = new JScrollPane(table);
add(createRow, java.awt.BorderLayout.NORTH);
add(scroll, java.awt.BorderLayout.CENTER);
createRowOn();
}
// while button is pressed then create A ROW
public void createRowOn() {
createRow.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == createRow) {
model.addRow(new Object[]{"", "", ""});
}
}
});
}
public static void main(String args[]) {
MyTable t = new MyTable();
t.setVisible(true);
t.setSize(300, 300);
}
}
Sorry for being so amateur
please read Oracle tutorial How to use Tables, especially part Creating Table Model
I created a 'button' on frame so that when we click the button for the
first time, A ROW will be inserted on frame. But all i want that when
i click the button on THE SECOND TIME , the ROW IS REFRESHED (Not
creating a new row !) , i suspect 'new Object[] { "", "", ""}' is the
cause , because the object is created everytime i click the button, so
how could i possibly modify the code ?
not clear from question (nothing is added to JTable) if you want to:
add a new row (model.addRow)
remove all rows (setDataVector/setRowCount)
reset value in JTables view (setValueAt)
but everything is described in Oracle tutorial, rest in the DefaultTableModel

how to update comboBox while using glazedList..evenlist

alright.,ive already tried every trick off my sleeves..but couldnt figure out how to update the comboBox w/glazedList..if the input is coming from other class..ive tried passing the value to the methods,declaring it first to a string..and such..but none has work..tho it does work if the new item will just gonna come from same class..via click of a button..
so far ive got this code..
values = GlazedLists.eventListOf(auto);//auto is an array..
AutoCompleteSupport.install(comboSearch,values);//comboSearch is the comboBox
//"x" is the value coming from another class.
public void updateCombo(String x){
List<String> item = new ArrayList<>();
item.add(x)
value.addAll(item);
}
i hope this codes are enough to interpret what im trying to ask..
It's not possible to see how you've created your combobox and your eventlist. Therefore I'll just create a simple example application from scratch that shows you the essentials.
Just in case you're not familiar the general concepts the main take home points are:
Try and avoid using standard Java collections (eg ArrayList, Vector) and use the EventList class as soon as possible. All the goodness that comes with sorting/filtering/auto-complete relies on the EventList foundation so set one up asap and then simply manipulate (add/remove/etc) and then the GlazedLists plumbing will take care of the rest.
Once you've got your collection of objects in an EventList and you want to leverage a swing component then look in the ca.odell.glazedlists.swing module which contains everything you need. In this instance you can use an EventListComboBoxModel - pass in your eventlist, and then set your JComboBox model to use the newly created EventListComboBoxModel and from that point GlazedLists will take care of ensuring your list data structure and combobox stay in sync.
So in my example I create an empty combobox and an button. Clicking the button will add an item per click into the combobox. The magic is simply the creation of the EventList and the use of EventListComboBoxModel to link the list to the combobox.
Please note that the code below was only tested against GlazedLists 1.8. But I'm pretty sure it'll work fine with 1.9 or 1.7 too.
public class UpdateComboBox {
private JFrame mainFrame;
private JComboBox cboItems;
private EventList<String> itemsList = new BasicEventList<String>();
public UpdateComboBox() {
createGUI();
}
private void createGUI() {
mainFrame = new JFrame("GlazedLists Update Combobox Example");
mainFrame.setSize(600, 400);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton addButton = new JButton("Add Item");
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
itemsList.add("Item " + (itemsList.size()+1));
}
});
// Use a GlazedLists EventComboBoxModel to connect the JComboBox with an EventList.
EventComboBoxModel<String> model = new EventComboBoxModel<String>(itemsList);
cboItems = new JComboBox(model);
JPanel panel = new JPanel(new BorderLayout());
panel.add(cboItems, BorderLayout.NORTH);
panel.add(addButton, BorderLayout.SOUTH);
mainFrame.getContentPane().add(panel);
mainFrame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new UpdateComboBox();
}
});
}
}

JTable won't refresh

Why won't table cell 0,1 change from aaa to XXXX?
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
class MainFrame {
public static void main(String[] args) {
JFrame f = new JFrame("Refreshing JTable");
JPanel p = new JPanel(new GridBagLayout());
DefaultTableModel productsModel;
JTable productsTable;
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] tableTitle = new String[] {"ID", "Name"};
String[][] tableData = {{"1", "AAA"},{"2", "BBB"}};
productsModel = new DefaultTableModel(tableData, tableTitle);
productsTable = new JTable(productsModel) {
public boolean isCellEditable(int r, int c) {
return false;
}
};
JScrollPane scrollpane = new JScrollPane(productsTable);
tableData[0][1] = "XXXX";
f.add(p);
p.add(scrollpane);
f.validate();
f.setVisible(true);
}
}
REASON:
Apparently trying to update the array where data is stored will result in JTable not changing. Either DefaultTableModel needs to be updated or the whole table needs to be redrawn.
EDIT (possible Solution) One way is using Timer:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
class MainFrame {
static JFrame f = new JFrame("Refreshing JTable");
static JPanel p = new JPanel(new GridBagLayout());
static DefaultTableModel productsModel;
static JTable productsTable;
public static void main(String[] args) {
runGui();
}
#SuppressWarnings("serial")
public static void runGui() {
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] tableTitle = new String[] {"ID", "Name"};
String[][] tableData = {{"1", "AAA"},{"2", "BBB"}};
productsModel = new DefaultTableModel(tableData, tableTitle);
productsTable = new JTable(productsModel) {
public boolean isCellEditable(int r, int c) {
return false;
}
};
JScrollPane scrollpane = new JScrollPane(productsTable);
tableData[0][1] = "XXXX";
Timer t = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
addColumns();
remakeData();
productsTable.setModel(productsModel);
}
});
t.start();
f.add(p);
p.add(scrollpane);
f.validate();
f.setVisible(true);
}
private static void addColumns() {
productsModel.setColumnCount(0);
productsModel.addColumn("ID");
productsModel.addColumn("Name");
}
private static void remakeData() {
productsModel.setRowCount(0);
productsModel.insertRow(productsModel.getRowCount(), new Object[] {"1", "Dummy item 1"});
productsModel.insertRow(productsModel.getRowCount(), new Object[] {"2", "Dummy itme 2"});
productsModel.insertRow(productsModel.getRowCount(), new Object[] {"3", "Dummy item 3"});
productsModel.insertRow(productsModel.getRowCount(), new Object[] {"4", "Dummy item 4"});
productsModel.insertRow(productsModel.getRowCount(), new Object[] {"5", "Dummy item 5"});
}
}
EDIT(much better solution, the way it worked for me flawlessly) Using a static method. Since I'm adding new data in array through another Frame, I created a static method in MainFrame, which I call every time I add/update/delete Object in array. This method will redo the whole model after update and will therefore refresh table.
One problem with the SSCCE posted on your related thread is that the code changes the array which originally formed the table model, whereas it should be changing the table model itself.
The solution to your problem (and the previous one) is rather simple, but unfortunately a bit too long to post it in a comment
You make sure you do some reading on how a JTable actually works. A good starting point is the Swing tutorial and perhaps even the class javadoc of the most important classes JTable and TableModel. Another good read about Swing and the use of MVC is this document. It is much broader then only JTables but will provide you with more insight in how all Swing components are designed, and how you should use them.
After reading that tutorial, you should understand that if you want to update the data which is shown in the table, you update the model of your table. The model will fire events which are received by the table, and the table will make sure it updates itself. After all, the table is only a view on the data (=the TableModel) so updates on the take should take place on the model side. If this is not clear, go back to step 1
Now take a look at your code and remove the listener. Instead, update the model on the table and see how the table updates itself.
If this does not work, you come back to this site with an SSCCE which you post. That way we can see that you tried something, what you tried and most likely what is wrong in your code. This SSCCE should include your code of the TableModel you use and the code that updates your TableModel since that is the most likely location for your problem.

Categories

Resources