The question is how swing handles listeners. In this example it is the TableModelListener
which is in focus.
The table model (let us call it TableModelImpl
) I have is extended from AbstractTableModel
. Between this table model and the JTable
I have class called TableSorter
, which is like a decorator to TableModelImpl
(and the TableSorter
also extends AbstractTableModel
). The TableSorter
is linked to TableModelImpl
via association, so what I mean is that TableSorter
holds a reference to the TableModelImpl
. Further, the TableSorter
have member of type TableModelListener
, which listen to my TableModelImpl
object. The JTable
does in turn listen to a TableSorter
.
So in general it can be said that the JTable
object listens to TableSorter
, which listens to my TableModelImpl
. So the question is: How does this work? Assume for example that I want to call TableModelStructureChanged()
on my TableModelImpl
object, will this Event be forwarded to the JTable
via the TableSorter
then?
So, some shortened example:
public class TableModelImpl extends AbstractTableModel {
private boolean enabled;
public TableModelImpl(//non relevant parameter, linked to data) {
//Irrelevant code binds model to the data
this.enabled = false;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
fireTableStructureChanged();
}
// More irrelevant code
}
public class TableSorter extends AbstractTableModel {
private TableModel tableModel;
private MouseListener mouseListener;
private TableModelListener tableModelListener;
public TableSorter() {
this.mouseListener = new MouseHandler();
this.tableModelListener = new TableModelHandler();
}
public TableSorter(TableModel tableModel) {
this();
setTableModel(tableModel); //Adds this.tableModelListener to tableModels listenerList
}
}
So if I do following:
TableModelImpl tm = new TableModelImpl();
TableSorter sorter = new TableSorter(tm);
JTable table = new JTable(sorter);
tm.setEnabled(true);
Will the JTable be notified?
Swing is a great implementation of most well-known design patterns in java such as Model-View-Controller
(most of times referred to as MVC), Singleton
, Factory
, Observer
and etc.
Many JComponents
such as JTable
, JList
or JComboBox
are implementing MVC pattern.
In many situations when the model is changed, a method like fireTableDataChanged()
is getting called, which is responsible for iterating over the list of listeners added to the model and call their tableChanged(TableModelEvent tme)
method. So any other component such as the view will be notified to update it's state due to the changes of the model.
The same is applied when fireTableStructureChanged()
is called. Since JTable
is implementing the TableModelListener
interface and register itself as a listener to it's TableModel
, it will be notified automatically when you call fireTableStructureChanged()
.
It's beneficial to see the source code of the JTable
and AbstractTableModel
to understand the mechanism of firing and listening to the TableModelEvent
s.
[UPDATE]
There is not a magic way, just method calls. In the AbstractTableModel
there is a List<TableModelListener>
called listenerList
. On the other hand, JTable
is implementing TableModelListener
interface. In the constructor of JTable
class, JTable
adds itself to the list of listeners in the model. So when anything happens to TableModel
and its fireXXX()
methods are getting called, the only magic is iterating over listenerList
and calling 'tableChanged' method. Since JTable
is in the list, then 'tableChanged' of JTable
is called.
Hope this would be helpful.