Swing 為輕量級、純 Java 實現,跨平台一致性優於 AWT(重量級、依賴原生 Peer)。雖然早期版本效能稍遜,但現代 JVM 優化後差距可忽略。Swing 提供豐富組件:JToolBar、JColorChooser、JFileChooser、JOptionPane 等,AWT 均無對應。
// 按鈕與圖示
Icon okIcon = new ImageIcon("ico/ok.png");
JButton ok = new JButton("確認", okIcon);
// 單選按鈕群組
JRadioButton male = new JRadioButton("男", true);
JRadioButton female = new JRadioButton("女", false);
ButtonGroup bg = new ButtonGroup();
bg.add(male); bg.add(female);
// 複選框
JCheckBox married = new JCheckBox("是否已婚?", false);
// 下拉選單與列表
String[] colors = {"紅色", "綠色", "藍色"};
JComboBox colorChooser = new JComboBox(colors);
JList colorList = new JList(colors);
// 文本域
JTextArea ta = new JTextArea(8, 20);
JTextField name = new JTextField(40);
JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("文件");
JMenu edit = new JMenu("編輯");
JMenu format = new JMenu("格式");
// 快捷鍵設置
newItem.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_MASK));
// 二級選單
edit.add(format);
// 右鍵選單:切換 LookAndFeel
JPopupMenu pop = new JPopupMenu();
ButtonGroup flavorGroup = new ButtonGroup();
JRadioButtonMenuItem metalItem = new JRadioButtonMenuItem("Metal風格", true);
JRadioButtonMenuItem windowsItem = new JRadioButtonMenuItem("Windows風格");
JRadioButtonMenuItem motifItem = new JRadioButtonMenuItem("Motif風格");
flavorGroup.add(metalItem); flavorGroup.add(windowsItem); flavorGroup.add(motifItem);
pop.add(metalItem); pop.add(windowsItem); pop.add(motifItem);
// 事件監聽器統一處理
ActionListener flavorListener = e -> {
try {
if ("Metal風格".equals(e.getActionCommand())) changeFlavor(1);
else if ("Windows風格".equals(e.getActionCommand())) changeFlavor(2);
else if ("Motif風格".equals(e.getActionCommand())) changeFlavor(3);
} catch (Exception ex) { ex.printStackTrace(); }
};
metalItem.addActionListener(flavorListener);
windowsItem.addActionListener(flavorListener);
motifItem.addActionListener(flavorListener);
// 安裝右鍵選單
ta.setComponentPopupMenu(pop);
private void changeFlavor(int flavor) throws Exception {
switch (flavor) {
case 1: UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); break;
case 2: UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); break;
case 3: UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); break;
}
SwingUtilities.updateComponentTreeUI(f.getContentPane());
SwingUtilities.updateComponentTreeUI(mb);
SwingUtilities.updateComponentTreeUI(pop);
}
Action copyAction = new AbstractAction("複製", new ImageIcon("ico/copy.png")) {
public void actionPerformed(ActionEvent e) {
StringSelection contents = new StringSelection(jta.getSelectedText());
clipboard.setContents(contents, null);
if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor))
pasteAction.setEnabled(true);
}
};
Action pasteAction = new AbstractAction("貼上", new ImageIcon("ico/paste.png")) {
public void actionPerformed(ActionEvent e) {
if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
try {
String content = (String) clipboard.getData(DataFlavor.stringFlavor);
jta.replaceRange(content, jta.getSelectionStart(), jta.getSelectionEnd());
} catch (Exception ex) { ex.printStackTrace(); }
}
}
};
// 同一 Action 同時加入工具列、選單、按鈕
jtb.add(copyAction); jtb.add(pasteAction);
edit.add(copyAction); edit.add(pasteAction);
JButton copyBn = new JButton(copyAction);
JButton pasteBn = new JButton(pasteAction);
// 模態對話框(一行搞定)
foreColor = JColorChooser.showDialog(f, "選擇畫筆顏色", foreColor);
// 非模態對話框(可自訂確認/取消回呼)
final JColorChooser colorPane = new JColorChooser(foreColor);
JDialog jd = JColorChooser.createDialog(f, "選擇畫筆顏色", false,
colorPane, e -> foreColor = colorPane.getColor(), null);
jd.setVisible(true);
JFileChooser chooser = new JFileChooser(".");
ExtensionFileFilter filter = new ExtensionFileFilter();
filter.addExtension("jpg"); filter.addExtension("png"); filter.addExtension("gif");
filter.setDescription("圖片檔案(*.jpg,*.png,*.gif)");
chooser.addChoosableFileFilter(filter);
chooser.setAcceptAllFileFilterUsed(false);
chooser.setFileView(new FileIconView(filter)); // 自訂檔案圖示
chooser.setAccessory(previewLabel); // 預覽區組件
// 監聽選取檔案變更,即時更新預覽
chooser.addPropertyChangeListener(e -> {
if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(e.getPropertyName())) {
File f = (File) e.getNewValue();
if (f != null) {
ImageIcon icon = new ImageIcon(f.getPath());
if (icon.getIconWidth() > PREVIEW_SIZE)
icon = new ImageIcon(icon.getImage().getScaledInstance(PREVIEW_SIZE, -1, Image.SCALE_DEFAULT));
previewLabel.setIcon(icon);
}
}
});
透過 showMessageDialog、showConfirmDialog、showInputDialog、showOptionDialog 四大靜態方法,支援字串、圖示、元件、物件陣列等多種訊息型態,按鈕配置靈活(YES/NO/CANCEL/OK 等)。
文中所有完整類別代碼(SwingComponent、TestJToolBar、HandDraw、ImageViewer、TestJOptionPane)均可直接複製運行,圖示資源請自行準備。