How to correctly update AbstractTableModel with fireTableDataChanged()?
Solution 1
from what I've read I shold be able to simply call fireTableDataChanged() on the model and the table should update itself
Your program doesn't invoke the fireXXX methods on the model. The TableModel itself is responsible for invoking these methods whenever any of the data in the model is changed. Look at the Creating a Table Model example from the Swing tutorial. The setValueAt(...) method shows how to invoke the appropriate fireXXX method.
If you create a completely new TableModel, then you need to use the setModel() method.
Kleopatra's comment was that all fireXXX methods showed be invoked from within the TableModel class itself. If you want to understand how this is done, then take a look at the source code for the DefaultTableModel. If has example of when you would invoke the fireTableDataChanged() method along with the other fireXXX methods.
Solution 2
You shouldn't have to replace the entire model to update a single row. Instead, update the affected cell(s) and let setValueAt()
fire the required event, as shown here. Alternatively, this related example uses a DefaultTableModel
that handles the events for you, as suggested by @mKorbel & @camickr.
If you stay with AbstractTableModel
, consider List<List<MyData>>
, unless you need Vector
for some other reason.
Solution 3
not to answer to your question, suggestion about using DefaultTableModel
if you don't need to something to restrict for JTable
, really good reason, then you couldn't to use AbstractTableModel, best job is still if you'd implement DefaultTableModel, by using DefaultTableModel
you'll never to care about that, which of FireXxxXxxChanged()
you have to use for each from setXxx()
methods,
s.d
Updated on June 04, 2022Comments
-
s.d almost 2 years
I'm still struggling with a
JTable
that should be automatically updated.The situation is as follows: I instantiate
MyTable
(extendsJTable
), and set it in my UI class (MyView
). TheMyTable
class takes the UI class and an instance of the class that contains logic as parameters):... private JPanel createTablePanel() { tablePanel = new JPanel(); myTable = new MyTable(this,mymeth); setMyTable(myTable); JScrollPane scrollPane = new JScrollPane(getMyTable()); tablePanel.add(scrollPane); return tablePanel; }
MyTable
itself looks like below. An extension ofAbstractTableModel
(MyTableModel
) is set to it. An extension ofTableModelListener
is set to the model. And finally an extension ofListSelectionListener
is set to the model'sSelectionModel
.public class MyTable extends JTable implements TableModelListener { public MyTable(MyView myView, MyMethods mymeth) { AbstractTableModel tableModel = new MyTableModel(mymeth); setModel(tableModel); getModel().addTableModelListener(new MyTableModelListener()); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setCellSelectionEnabled(true); getColumnModel().getSelectionModel().addListSelectionListener(new MyTableSelectionListener(this, mymeth, myView)); setPreferredScrollableViewportSize(this.getPreferredSize()); } }
Let's have a quick look at the model's constructor.
public MyTableModel(MyMethods mymeth) { dataObject = new MyData(mymeth); myData = dataObject.getMyData(); colTitles = dataObject.getColTitles(); }
MyData
compiles the data for the table: AVector<Vector<Object>>
, that consists of threeVector<Object>
s (the table data) and aString[]
(The column titles). The data itself comes from a graph viamymeth
, the logic class' instance.Whenever a table column is clicked, a popup (i.e.
JOptionPane
) object is instantiated, which presents a selection of values for the 3rd row in the selected column. The user chooses a value and the value is set to the data model. Note the way the table is updated after that.public MyOptionPane(int i, MyMethods mymeth, MyView myView) { this.view = myView; String sourceString = mymeth.getSourceString(i); // Gets a String from a String[]. In this Array, the order is the same as in the table. String tag = null; tag = (String) JOptionPane.showInputDialog(this, "Choose a tag for \"" + sourceString + "\"", "String tagging" , JOptionPane.PLAIN_MESSAGE, null, myView.getTags().toArray(), myView.getTags().get(0)); mymeth.setTag(i, tag); // This is where fireTableDataChanged() didn't work, but this did MyTableModel model = new MyTableModel(mymeth); // New model instance view.getMyTable().setModel(model); // reset new model to table }
This works. However, from what I've read I shold be able to simply call
fireTableDataChanged()
on the model and the table should update itself. However, this doesn't work. User kleopatra has commented to an answer in a previous post:do not call any of the model's fireXX methods from any code external to the model. Instead implement the model to do so when anything changed
So: Can I call
fireTableDataChanged()
within such a structure at all? And if so, where and how?Thanks in advance for all pieces of enlightenment!