XTree 組件開發。JSplitPane + JScrollPane)、XTree 增強(默認歡迎樹、錯誤容錯)、XmlEditor 主視窗構建。本文完善菜單系統、文件打開/保存、退出確認對話框,打造一個功能完整的桌面級 XML 編輯器。
JMenuBar (菜單欄)
└─ JMenu "File" (文件菜單)
├─ JMenuItem "New" (新建)
├─ JMenuItem "Open" (打開)
├─ JMenuItem "Save" (保存)
├─ JSeparator
└─ JMenuItem "Exit" (退出)
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F); // Alt+F 快捷鍵
// 新建
JMenuItem newItem = new JMenuItem("New", KeyEvent.VK_N);
newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK));
newItem.addActionListener(new NewAction());
// 打開
JMenuItem openItem = new JMenuItem("Open...", KeyEvent.VK_O);
openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
openItem.addActionListener(new OpenAction());
// 保存
JMenuItem saveItem = new JMenuItem("Save", KeyEvent.VK_S);
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
saveItem.addActionListener(new SaveAction());
// 退出
JMenuItem exitItem = new JMenuItem("Exit", KeyEvent.VK_X);
exitItem.addActionListener(new ExitAction());
fileMenu.add(newItem);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.addSeparator();
fileMenu.add(exitItem);
menuBar.add(fileMenu);
setJMenuBar(menuBar);
每個菜單項對應獨立 ActionListener 實現類,便於復用與測試:
class ExitAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
verifyDialog.setVisible(true); // 顯示確認對話框
}
}
class XmlFileFilter extends FileFilter {
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith(".xml");
}
public String getDescription() { return "XML Files (*.xml)"; }
}
class OpenAction implements ActionListener {
private final JFileChooser chooser = new JFileChooser();
private final Container parent;
OpenAction(Container parent) {
this.parent = parent;
chooser.setFileFilter(new XmlFileFilter());
chooser.setPreferredSize(new Dimension(500, 300));
}
public void actionPerformed(ActionEvent e) {
if (chooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
textArea.read(reader, null); // JTextArea 直接讀取
xTree.refresh(textArea.getText()); // 同步更新樹視圖
chooser.setCurrentDirectory(file.getParentFile());
} catch (IOException ex) {
showError("打開失敗: " + ex.getMessage());
}
}
}
}
class SaveAction implements ActionListener {
private final JFileChooser chooser = new JFileChooser();
private final Container parent;
SaveAction(Container parent) {
this.parent = parent;
chooser.setFileFilter(new XmlFileFilter());
}
public void actionPerformed(ActionEvent e) {
if (chooser.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
// 自動補全 .xml 後綴
if (!file.getName().toLowerCase().endsWith(".xml")) {
file = new File(file.getParentFile(), file.getName() + ".xml");
}
try (FileWriter writer = new FileWriter(file)) {
textArea.write(writer);
chooser.setCurrentDirectory(file.getParentFile());
} catch (IOException ex) {
showError("保存失敗: " + ex.getMessage());
}
}
}
}
JDialog verifyDialog = new JDialog(this, "Confirm Exit", true); // 模態對話框
verifyDialog.setLayout(new FlowLayout());
verifyDialog.add(new JLabel("Are you sure you want to exit? Unsaved changes will be lost."));
JButton okBtn = new JButton("OK");
okBtn.addActionListener(e -> System.exit(0));
JButton cancelBtn = new JButton("Cancel");
cancelBtn.addActionListener(e -> verifyDialog.setVisible(false));
verifyDialog.add(okBtn);
verifyDialog.add(cancelBtn);
verifyDialog.pack();
verifyDialog.setLocationRelativeTo(this); // 居中顯示
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
verifyDialog.setVisible(true); // 用戶點擊右上角 X 時彈出確認
}
});
XmlEditor extends JFrame implements ActionListener {
// 組件
XTree xTree;
JTextArea textArea;
JDialog verifyDialog;
JFileChooser openChooser, saveChooser;
// 內部類:NewAction, OpenAction, SaveAction, ExitAction, XmlFileFilter
// 主入口 main():支援命令行參數打開文件,或啟動默認歡迎界面
}
至此,一個具備語法高亮、樹文本雙視圖同步、文件操作、誤操作防護的 XML 編輯器核心已成型。後續可擴展:
RSyntaxTextArea 實現 XML 語法高亮與自動縮進。java -jar xmleditor.jar 一鍵啟動。Swing 雖非主流,但其輕量、跨平台、無外部依賴特性,仍是桌面工具快速開發的利器。