Swing Icon 接口雖簡單(僅三方法),卻支撐起強大的圖標合成、裝飾、過濾與狀態管理能力。本文實戰開發 JIcon 組件,實現圖標列表循環顯示、鍵鼠交互切換、焦點高亮、模型-視圖分離,適用於日誌級別標識、表格狀態列、樹節點圖標等場景。附完整工具類庫(CompoundIcon、DecoratorIcon、FilterIcon)設計解析。
CompoundIcon(Icon icon1, Icon icon2, boolean horizontal)JLabel、JButton)DecoratorIcon(Icon base, Icon overlay, int vAlign, int hAlign)IllegalArgumentExceptionFilterIcon(Icon base, ImageFilter filter)ImageFilter 與 Java 2D BufferedImageFilterpublic interface IconListModel extends Icon {
int getIconCount();
int getCurrentIndex();
Icon getIcon(int index);
void setIcons(Icon[] icons);
void addIcon(Icon icon);
void removeIcon(Icon icon);
void setCurrentIcon(int index);
// ChangeListener 支持
void addChangeListener(ChangeListener l);
void removeChangeListener(ChangeListener l);
}
List 與 ListgetIconWidth/Height() 返回列表最大尺寸(緩存)paintIcon() 委派給當前索引圖標fireChangeEvent() 通知視圖重繪public class JIcon extends JComponent implements
ChangeListener, FocusListener, MouseListener, KeyListener { ... }
| 特性 | 實現細節 |
|---|---|
| 默認邊框 | 1px EmptyBorder,焦點時切換為藍色 LineBorder |
| 焦點控制 | setFocusable(true),Java 1.4+ 用 isFocusable(),舊版用 isFocusTraversable() |
| 鍵盤交互 | 空格鍵 → nextIcon() 循環切換 |
| 鼠標交互 | 點擊獲取焦點 → nextIcon();可擴展右鍵 prevIcon() |
| 循環邏輯 | nextIcon():索引+1 取模;prevIcon():索引-1 取模 |
| 尺寸自適應 | 模型變更觸發 resetSize() 更新 preferred/minimum size |
// 構建圖標列表:空框、勾選、叉號
Icon[] states = { new CheckBoxIcon(false), new CheckBoxIcon(true), new CheckBoxIcon(null) };
IconListModel model = new IconListModelImpl(states);
JIcon jicon = new JIcon(model);
jicon.setFocusable(true);
panel.add(jicon);
// 程序化切換
jicon.setCurrentIcon(1); // 顯示勾選狀態
table.getColumn("status").setCellRenderer(new JIconRenderer(model))| 模式 | 應用點 |
|---|---|
| 裝飾器 | DecoratorIcon、CompoundIcon、FilterIcon 透明包裝 Icon |
| 觀察者 | IconListModel 發布 ChangeEvent,JIcon 訂閱重繪 |
| 狀態 | JIcon 委派給模型當前索引圖標渲染 |
| 組合 | CompoundIcon 遞歸組合任意深度圖標樹 |
JIcon 填補了 Swing 無原生多狀態圖標組件的空白,讓圖標不再是靜態裝飾,而成為可交互、可編程、可組合的狀態視圖單元。