優秀的 Swing 應用遵循「以數據為中心,而非以 UI 為中心」的設計原則。Swing 為每個帶邏輯數據的組件定義了獨立的 Model 接口,實現視圖與模型分離,支持開發者注入自定義模型實現。本文系統梳理 Swing Model 體系、分類、共享機制、編程接口與變更通知模式。
| 組件 | Model 接口 | 模型類型 |
|---|---|---|
| JButton/JToggleButton/JCheckBox/JRadioButton | ButtonModel | GUI 狀態 / 應用數據 |
| JMenu/JMenuItem/JCheckBoxMenuItem/JRadioButtonMenuItem | ButtonModel | GUI 狀態 / 應用數據 |
| JComboBox | ComboBoxModel | 應用數據 |
| JProgressBar/JScrollBar/JSlider | BoundedRangeModel | GUI 狀態 / 應用數據 |
| JTabbedPane | SingleSelectionModel | GUI 狀態 |
| JList | ListModel / ListSelectionModel | 應用數據 / GUI 狀態 |
| JTable | TableModel / TableColumnModel | 應用數據 / GUI 狀態 |
| JTree | TreeModel / TreeSelectionModel | 應用數據 / GUI 狀態 |
| JEditorPane/JTextPane/JTextArea/JTextField/JPasswordField | Document | 應用數據 |
setSelected()、getValue())已足夠如 BoundedRangeModel(Slider/ScrollBar/ProgressBar),既包含數據範圍(應用),又包含當前值/調整狀態(GUI)。
多組件共享同一模型接口定義,可實現自動狀態同步:
// JSlider 和 JScrollBar 共享 BoundedRangeModel
BoundedRangeModel sharedModel = new DefaultBoundedRangeModel();
JSlider slider = new JSlider(sharedModel);
JScrollBar scrollBar = new JScrollBar(sharedModel, Adjustable.HORIZONTAL);
// 拖動滑塊 → 滾動條同步移動,零代碼耦合

使用模型的組件必須提供標準 getter/setter:
public BoundedRangeModel getModel()
public void setModel(BoundedRangeModel model)
Default + 接口名(如 DefaultBoundedRangeModel、DefaultListModel)public JSlider(int orientation, int min, int max, int value) {
this.model = new DefaultBoundedRangeModel(value, 0, min, max);
this.model.addChangeListener(changeListener);
updateUI();
}
JSlider slider = new JSlider();
BoundedRangeModel customModel = new DefaultBoundedRangeModel() {
@Override public void setValue(int n) {
System.out.println("SetValue: " + n); // 攔截值變更
super.setValue(n);
}
};
slider.setModel(customModel); // 替換默認模型
| 組件 | 接口 | 抽象實現 | 具體默認實現 |
|---|---|---|---|
| JList | ListModel | AbstractListModel | DefaultListModel |
| JTable | TableModel | AbstractTableModel | DefaultTableModel |
| JTree | TreeModel | AbstractTreeModel | DefaultTreeModel |
| 通知類型 | 特點 | 適用場景 | 示例 |
|---|---|---|---|
| 輕量級通知 | 單一事件實例復用,僅通知「狀態已變」 | 高頻變更,視圖自行查詢詳情 | JScrollBar 拖動、Slider 滑動 |
| 狀態化通知 | 每次創建新事件對象,攜帶詳細變更信息 | 變更複雜,查詢成本高 | JTable 某列數據變更、Tree 節點增刪 |
ChangeEvent:輕量級(BoundedRangeModel、ButtonModel、SingleSelectionModel)ListDataEvent:ListModel 內容增刪TableModelEvent:TableModel 細粒度變更(行/列/單元格)TreeModelEvent:TreeModel 結構變更DocumentEvent:Document 文本變更