Java Swing 中的侦听器是如何处理的?

How are listeners handled in Java Swing?

问题是 swing 如何处理听众。在此示例中,焦点是 TableModelListener

我拥有的 table 模型(我们称之为 TableModelImpl)是从 AbstractTableModel 扩展而来的。在这个 table 模型和 JTable 之间,我有 class 称为 TableSorter,它就像 TableModelImpl 的装饰器(并且 TableSorter 也扩展了AbstractTableModel)。 TableSorter 通过关联链接到 TableModelImpl,所以我的意思是 TableSorter 持有对 TableModelImpl 的引用。此外,TableSorter 具有 TableModelListener 类型的成员,它监听我的 TableModelImpl 对象。 JTable 确实反过来听 TableSorter.

所以一般来说可以说JTable对象监听TableSorter,它监听我的TableModelImpl。所以问题是:这是如何工作的?例如,假设我想在我的 TableModelImpl 对象上调用 TableModelStructureChanged(),那么这个事件会通过 TableSorter 转发到 JTable 吗?

所以,一些简短的例子:

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

所以如果我执行以下操作:

TableModelImpl tm = new TableModelImpl();
TableSorter sorter = new TableSorter(tm);
JTable table = new JTable(sorter);
tm.setEnabled(true);

是否会通知 JTable?

Swing 是 java 中大多数知名设计模式的出色实现,例如 Model-View-Controller(大多数时候称为 MVC), SingletonFactoryObserver

许多 JComponents,例如 JTableJListJComboBox 正在实施 MVC 模式。

在许多情况下,当模型发生变化时,会调用类似 fireTableDataChanged() 的方法,该方法负责遍历添加到模型的侦听器列表并调用它们的 tableChanged(TableModelEvent tme) 方法。因此,由于模型的更改,任何其他组件(例如视图)将被通知更新其状态。

调用fireTableStructureChanged()时也是如此。由于 JTable 正在实现 TableModelListener 接口并将自己注册为它的 TableModel 的侦听器,因此当您调用 fireTableStructureChanged().

时它会自动收到通知

查看 JTableAbstractTableModel 的源代码有助于理解触发和收听 TableModelEvent 的机制。

[更新]

没有神奇的方法,只有方法调用。在AbstractTableModel中有一个叫做listenerListList<TableModelListener>。另一方面,JTable 正在实现 TableModelListener 接口。在 JTable class 的构造函数中,JTable 将自己添加到模型中的侦听器列表中。所以当 TableModel 发生任何事情并且它的 fireXXX() 方法被调用时,唯一的魔法就是遍历 listenerList 并调用 'tableChanged' 方法。由于 JTable 在列表中,因此 'tableChanged' of JTable 被调用。

希望这会有所帮助。