實現一個模態對話框 FontDialog,包含字體名稱下拉框、字體大小下拉框、預覽標籤、確定/取消按鈕。主窗口點擊「設置字體」彈出對話框,用戶確定後將選中的字體應用到主窗口文本區。
// 錯誤:構造函數中先調用 init(),但 init() 內使用 button 前未 new
public Window1() {
button.addActionListener(this); // button 為 null
init();
}
// 正確:init() 內完成所有組件創建
public Window1() {
init(); // 內部 new JButton()、addActionListener()
setVisible(true);
}
setModal(true); // 必須在 setVisible(true) 前調用,阻塞主窗口交互
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames(); // 系統安裝的所有字體
使用 Lambda 表達式(Java 8+)或統一實現 ItemListener/ActionListener 接口,避免匿名內部類冗余。
// FontDialog.java
public class FontDialog extends JDialog implements ItemListener, ActionListener {
private JComboBox<String> fontNameBox, fontSizeBox;
private JLabel previewLabel;
private String selectedFont = "Serif";
private int selectedSize = 24;
private boolean confirmed = false;
public FontDialog(Frame owner) {
super(owner, "字體設置", true); // 模態
initComponents();
pack();
setLocationRelativeTo(owner);
}
private void initComponents() {
// 字體列表
fontNameBox = new JComboBox<>(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
fontNameBox.addItemListener(this);
// 大小列表
Integer[] sizes = new Integer[72];
for (int i = 0; i < 72; i++) sizes[i] = i + 8;
fontSizeBox = new JComboBox<>(sizes);
fontSizeBox.addItemListener(this);
// 預覽
previewLabel = new JLabel("預覽文字 Preview");
updatePreview();
// 按鈕
JButton ok = new JButton("確定");
JButton cancel = new JButton("取消");
ok.addActionListener(e -> { confirmed = true; dispose(); });
cancel.addActionListener(e -> dispose());
// 佈局...
}
@Override public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
updatePreview();
}
}
private void updatePreview() {
selectedFont = (String) fontNameBox.getSelectedItem();
selectedSize = (Integer) fontSizeBox.getSelectedItem();
previewLabel.setFont(new Font(selectedFont, Font.PLAIN, selectedSize));
}
public Font getSelectedFont() { return new Font(selectedFont, Font.PLAIN, selectedSize); }
public boolean isConfirmed() { return confirmed; }
}
// 主窗口調用
JButton btnFont = new JButton("設置字體");
btnFont.addActionListener(e -> {
FontDialog dialog = new FontDialog(this);
dialog.setVisible(true);
if (dialog.isConfirmed()) {
textArea.setFont(dialog.getSelectedFont());
}
});
FontDialog、MainWindow)。fontNameBox)。initComponents() 中,構造函數保持簡潔。