电话
400 9058 355
简易记事本必须用SwingUtilities.invokeLater启动EDT,JTextArea需启用换行,关闭前用DocumentListener检测修改并提示保存,读写文件须显式指定UTF-8编码,且区分currentFile与lastSavedTo管理路径。
JFrame + JTextArea 搭出基础界面,别碰 SwingUtilities.invokeLater 就跑不起来Java 简易记事本的核心不是功能多全,而是能立刻打开、输入、保存、再打开——界面必须在事件分发线程(EDT)里构建。漏掉 SwingUtilities.invokeLater,窗口可能黑屏、无响应,甚至 JTextArea 不接收键盘输入。
JFrame、JTextArea、JMenuBar)必须包在 SwingUtilities.invokeLater 里初始化JTextArea 要设 setLineWrap(true) 和 setWrapStyleWord(true),否则长行直接撑破窗口JFrame.pack() 后直接 setVisible(true) 就完事——先调 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE),否则点关闭就彻底退出,来不及弹保存提示Files.readAllLines 和 Files.write,别手写 BufferedReader / FileWriter
Java 7+ 的 Files 工具类封装了编码、异常、资源释放细节,比手动开流安全得多。尤其 Windows 记事本默认存为 GBK,而 Java 默认用 UTF-8 读会乱码——必须显式指定字符集。
Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8),拼成字符串用 String.join("\n", lines)
Files.write(Paths.get(filePath), content.getBytes(StandardCharsets.UTF_8)),别用 getOutputStream() 再套 Writer,容易漏 flushGBK 编码——可加试探逻辑:先按 UTF-8 读,捕获 MalformedInputException 后改用 GBK
DocumentListener 判断是否修改,而不是靠布尔标记靠 boolean isModified 手动开关,极易不同步:粘贴、撤销、拖入文本都会漏触发。真正可靠的修改状态,得监听 JTextArea.getDocument() 的底层变更。
textArea.getDocument() 添加 DocumentListener,在 insertUpdate、removeUpdate、changedUpdate 里统一设 isModified = true
document.removeDocumentListener(...),再 document.addDocumentListener(...),避免重复监听if (isModified) { showSaveDialog(); },但注意:用户点“不保存”后,要重置 isModified = false,否则下次关窗又弹很多初学者把“保存”和“另存为”共用一个 currentFile 字段,但“另存为”选新路径后没更新它,导致后续点“保存”仍写回旧文件——这会让用户以为内容丢了。
private File currentFile;(当前编辑的源文件)和 private File lastSavedTo;(上次实际写入位置),区分语义currentFile = selectedFile 和 lastSavedTo = selectedFile
lastSavedTo;若为 null(即首次保存),则跳转到“另存为”流程saveMenuItem.setEnabled(lastSavedTo != null || currentFile != null),避免灰掉却无法操作public class SimpleNotepad {
private JFrame frame;
private JTextArea textArea;
private File currentFile;
private File lastSavedTo;
public SimpleNotepad() {
SwingUtilities.invokeLater(() -> {
frame = new JFrame("简易记事本");
textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
frame.add(new JScrollPane(textArea));
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setSize(600, 400);
setupMenu();
setupCloseHandler();
frame.setVisible(true);
});
}
private void setupCloseHandler() {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (isModified()) {
int result = JOptionPane.showConfirmDialog(frame,
"内容已修改,是否保存?", "确认", JOptionPane.YES_NO_CANCEL_OPTION);
if (result == JOptionPane.YES_OPTION) {
save();
frame.dispose();
} else if (result == JOptionPane.NO_OPTION) {
frame.dispose();
}
} else {
frame.dispose();
}
}
});
}
private boolean isModified() {
// 实际项目中这里应结合 DocumentListener 状态判断
return false; // 占位,真实逻辑见上文 DocumentListener 部分
}
private void save() {
if (lastSavedTo != null) {
writeToFile(lastSavedTo, textArea.getText());
} else {
saveAs();
}
}
private void saveAs() {
JFileChooser chooser = new JFileChooser();
int result = chooser.showSaveDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
if (!file.getName().endsWith(".txt")) {
file = new File(file.getParent(), file.getName() + ".txt");
}
writeToFile(file, textArea.getText());
currentFile = file;
lastSavedTo = file;
}
}
private void writeToFile(File file, String content) {
try {
Files.write(file.toPath(), content.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
JOptionPane.showMessageDialog(frame, "保存失败:" + e.getMessage());
}
}
public static void main(String[] args) {
new SimpleNotepad();
}
}
文件编码兼容性、修改状态同步、保存路径管理——这三个点卡住绝大多数人的第一版实现。尤其是“另存为”后忘记更新 currentFile,问题会延迟暴露:用户编辑半小时,点“保存”却写进上周的文件里。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...