Java实现记事本知识小结

记事本按整体被分为三个部分(阶段),一个是图形的构建,一个是在图形界面上添加的功能,最后一个部分是实现这些功能的逻辑。
主要用的是swing,然后注册event等各种监听事件,最后是在监听到用户操作时执行相应的业务逻辑。
以下主要是创建记事本界面用到的类,包括窗口、菜单条、编辑区、最下面的状态栏、滚动条、右键菜单等等,重点是swing里是用名称表达的,比如菜单类Jmenu,文本区JtextArea,顾名思义即可:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

界面如下:
这里写图片描述

感觉最简单就是界面这一块,只要创建好小的容器,然后一级级的添加进大的容器里就可以,比如Jmenu.add(JmenuItem),Jmenubar.add(Jmenu)、JFrame.add(Jmenubar)、JFrame.add(JTextArea).

整个界面完成之后,给每个菜单项以及右键菜单的每个项添加ActionListener监听,这里的主类已经实现了监听接口,所以在main和构造方法里创建好界面之后,直接在下面重写接口的所有方法,这里就一个:

public interface ActionListener extends EventListener {

    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);

}

当用户操作时, actionPerformed(ActionEvent e)会被执行并且获得事件,然后用e.getSource()获得事件源,判断事件源是哪个对象,比如如果是if(e.getSource() == exitButton),那么就开始执行{是否有文件未保存?是否要退出?}。
由于事件源太多,在actionPerformed里实现所有逻辑代码过于臃长,所以
先把方法抽调出来,然后再在各个方法体里实现具体功能:

public void actionPerformed(ActionEvent e) {

    if (e.getSource() == popupMenu_Cut || e.getSource() == menuEdit_cut) {//
            copy();
            editArea.replaceSelection("");
        } else if (e.getSource() == popupMenu_Copy || e.getSource() == menuEdit_copy) {//
            copy();
        } else if (e.getSource() == popupMenu_Paste || e.getSource() == menuEdit_paste) {//
        } else if (e.getSource() == popupMenu_Delete || e.getSource() == menuEdit_delete) {//
            editArea.replaceSelection("");
        } else if (e.getSource() == popupMenu_SelectAll || e.getSource() == menuEdit_selectAll) {//
            editArea.selectAll();
        } else if (e.getSource() == menuFile_new) {//
            newFile();
        } else if (e.getSource() == menuFile_open) {//
            open();
        } else if (e.getSource() == menuFile_save) {//
            if (isChanged)
                save();
        } else if (e.getSource() == menuFile_saveas) {//
            saveAs();
        } else if (e.getSource() == menuFile_exit) {//
            doSomethingOnWindowClosing();
        } else if (e.getSource() == menuEdit_find) {
            find();
        } else .....

比如另存为的方法长这样:

    private void saveAs() {
        JFileChooser fileChooser = new JFileChooser("C:\\");
        fileChooser.setDialogTitle("另存为");
        // fileChooser.setApproveButtonText("确定");
        if (absoluteFile != null) {
            fileChooser.setSelectedFile(absoluteFile);
        }
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);// 有文件名才能点确定
        int result = fileChooser.showSaveDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {// 选择文件名后确定
            File filename = fileChooser.getSelectedFile();
            if (!filename.getPath().endsWith(".txt")) {
                String path = filename.getAbsolutePath() + ".txt";
                filename = new File(path);
            }
            if (filename.exists() && JFileChooser.APPROVE_OPTION != JOptionPane.showOptionDialog(this,
                    filename.getName() + " 已存在,是否要替换?", "确认另存为", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
                    null, null, null)) {
            } else {
                new FileWriteThread(editArea, filename).start(); // 使用多线程另存文件
                this.isChanged = false;
                absoluteFile = filename;
                this.setTitle(absoluteFile.getName());
            }
        } else {
            // 取消、关闭提示框,返回
        }
    }

由于要监听的按钮实在太多,强烈建议使用内部类,像这样直接又方便:

cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                replaceDialog.dispose();
            }
        });

对我来说最拖时间的是布局管理器和性能提升这两个方面。
比如这两个界面神烦:
这里写图片描述
这里写图片描述
窗口里头的组件各种错位,最后逼不得已用绝对定位setBounds(x,y,width,height)处理了一个,然后用gridbaglayout(格子、袋布局,很强大,每个格子大小自定,位置自定,组件大小、内外边距、拉伸比例或者不能拉伸自定等),另外还有水平排列、垂直排列,行和列排列等一些布局管理器,很整齐所以也没有那么灵活。据说Frame容器默认的是border管理器,也就是东南西北中五个位置,而Jpanel是Flowlayout,也就是流动的一行放不下流动到下一行。
做完界面、按钮等之后就到实现打开、保存、剪切、查找、替换、字体等功能了。
大概上是这样的,打开文件,先判断是否有正在编辑的内容未被保存,如有提示是否保存,然后再跳出一个JFileChooser(看名字就知道干嘛的了),用户选择完文件后判断Unicode、asni、UTF-8或者默认然后使用输入流读入文本到textArea。保存呢当确定保存后如果是新建文件同样需要选择保存位置和文件名,否则直接写入原有的文件。剪切复制粘贴这些用的是java一些api组合而成。查找先获取光标位置,按用户是否区分大小写和方向截断一个String,用lastindexof或者indexof,不过我是按512K字符分块查找的。全部替换一开始用的是递归,从前面找到先压入栈,找完后在从文本后替换回来(如果前面先替换后面位置就乱了),最后打开一个10m的文件一替换递归方法被调用3700次就stackoverflow了,所以只能分块替换或者全部提取到一个String里头查找替换平行进行。后来用Windows的notepad.exe测一下,写一个有20M个你字的txt文件让它替换,竟然过一会就替换完了怎么做到的!!我自己的测下卡死了。这里我主要考虑的是减少内存的消耗和时间的消耗,提升流畅性,看看以后有啥好的算法。
最后想着弄个exe文件的不过精简jre这块没做好太大没有什么打包的欲望,不过还是做了个exe,在main函数里加上:

if (args.length > 0 && args[0].contains(":")) {
            File file = new File(args[0]);
            notepad.openFile(file);
        }

这样直接在拖文件到exe上就可以打开了。
源码1500行就不贴了,把源码和文件附上,供学习交流,如果发现大bug和有好的修改建议,直接评论区。
附件地址:上传了没看见在哪。。。

  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
import java.awt.BorderLayout; import java.awt.Container; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.KeyStroke; import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; public class JNotePadUI extends JFrame { private JMenuItem menuOpen; private JMenuItem menuSave; private JMenuItem menuSaveAs; private JMenuItem menuClose; private JMenu editMenu; private JMenuItem menuCut; private JMenuItem menuCopy; private JMenuItem menuPaste; private JMenuItem menuAbout; private JTextArea textArea; private JLabel stateBar; private JFileChooser fileChooser; private JPopupMenu popUpMenu; public JNotePadUI() { super("新建文本文件"); setUpUIComponent(); setUpEventListener(); setVisible(true); } private void setUpUIComponent() { setSize(640, 480); // 菜单栏 JMenuBar menuBar = new JMenuBar(); // 设置「文件」菜单 JMenu fileMenu = new JMenu("文件"); menuOpen = new JMenuItem("打开"); // 快捷键设置 menuOpen.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_O, InputEvent.CTRL_MASK)); menuSave = new JMenuItem("保存"); menuSave.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_S, InputEvent.CTRL_MASK)); menuSaveAs = new JMenuItem("另存为"); menuClose = new JMenuItem("关闭"); menuClose.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_Q, InputEvent.CTRL_MASK)); fileMenu.add(menuOpen); fileMenu.addSeparator(); // 分隔线 fileMenu.add(menuSave); fileMenu.add(menuSaveAs); fileMenu.addSeparator(); // 分隔线 fileMenu.add(menuClose); // 设置「编辑」菜单 JMenu editMenu = new JMenu("编辑"); menuCut = new JMenuItem("剪切"); menuCut.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK)); menuCopy = new JMenuItem("复制"); menuCopy.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)); menuPaste = new JMenuItem("粘贴"); menuPaste.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK)); editMenu.add(menuCut); editMenu.add(menuCopy); editMenu.add(menuPaste); // 设置「关于」菜单 JMenu aboutMenu = new JMenu("关于"); menuAbout = new JMenuItem("关于JNotePad"); aboutMenu.add(menuAbout); menuBar.add(fileMenu); menuBar.add(editMenu); menuBar.add(aboutMenu); setJMenuBar(menuBar); // 文字编辑区域 textArea = new JTextArea(); textArea.setFont(new Font("宋体", Font.PLAIN, 16)); textArea.setLineWrap(true); JScrollPane panel = new JScrollPane(textArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); Container contentPane = getContentPane(); contentPane.add(panel, BorderLayout.CENTER); // 状态栏 stateBar = new JLabel("未修改"); stateBar.setHorizontalAlignment(SwingConstants.LEFT); stateBar.setBorder( BorderFactory.createEtchedBorder()); contentPane.add(stateBar, BorderLayout.SOUTH); popUpMenu = editMenu.getPopupMenu(); fileChooser = new JFileChooser(); } private void setUpEventListener() { // 按下窗口关闭钮事件处理 addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { closeFile(); } } ); // 菜单 - 打开 menuOpen.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { openFile(); } } ); // 菜单 - 保存 menuSave.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { saveFile(); } } ); // 菜单 - 另存为 menuSaveAs.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { saveFileAs(); } } ); // 菜单 - 关闭文件 menuClose.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { closeFile(); } } ); // 菜单 - 剪切 menuCut.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { cut(); } } ); // 菜单 - 复制 menuCopy.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { copy(); } } ); // 菜单 - 粘贴 menuPaste.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { paste(); } } ); // 菜单 - 关于 menuAbout.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { // 显示对话框 JOptionPane.showOptionDialog(null, "程序名称:\n JNotePad \n" + "程序设计:\n \n" + "简介:\n 一个简单的文字编辑器\n" + " 可作为验收Java实现对象\n" + " 欢迎网友下载研究交流\n\n" + " /", "关于JNotePad", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, null, null); } } ); // 编辑区键盘事件 textArea.addKeyListener( new KeyAdapter() { public void keyTyped(KeyEvent e) { processTextArea(); } } ); // 编辑区鼠标事件 textArea.addMouseListener( new MouseAdapter() { public void mouseReleased(MouseEvent e) { if(e.getButton() == MouseEvent.BUTTON3) popUpMenu.show(editMenu, e.getX(), e.getY()); } public void mouseClicked(MouseEvent e) { if(e.getButton() == MouseEvent.BUTTON1) popUpMenu.setVisible(false); } } ); } private void openFile() { if(isCurrentFileSaved()) { // 文件是否为保存状态 open(); // 打开 } else { // 显示对话框 int option = JOptionPane.showConfirmDialog( null, "文件已修改,是否保存?", "保存文件?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null); switch(option) { // 确认文件保存 case JOptionPane.YES_OPTION: saveFile(); // 保存文件 break; // 放弃文件保存 case JOptionPane.NO_OPTION: open(); break; } } } private boolean isCurrentFileSaved() { if(stateBar.getText().equals("未修改")) { return false; } else { return true; } } private void open() { // fileChooser 是 JFileChooser 的实例 // 显示文件选取的对话框 int option = fileChooser.showDialog(null, null); // 使用者按下确认键 if(option == JFileChooser.APPROVE_OPTION) { try { // 开启选取的文件 BufferedReader buf = new BufferedReader( new FileReader( fileChooser.getSelectedFile())); // 设定文件标题 setTitle(fileChooser.getSelectedFile().toString()); // 清除前一次文件 textArea.setText(""); // 设定状态栏 stateBar.setText("未修改"); // 取得系统相依的换行字符 String lineSeparator = System.getProperty("line.separator"); // 读取文件并附加至文字编辑区 String text; while((text = buf.readLine()) != null) { textArea.append(text); textArea.append(lineSeparator); } buf.close(); } catch(IOException e) { JOptionPane.showMessageDialog(null, e.toString(), "开启文件失败", JOptionPane.ERROR_MESSAGE); } } } private void saveFile() { // 从标题栏取得文件名称 File file = new File(getTitle()); // 若指定的文件不存在 if(!file.exists()) { // 执行另存为 saveFileAs(); } else { try { // 开启指定的文件 BufferedWriter buf = new BufferedWriter( new FileWriter(file)); // 将文字编辑区的文字写入文件 buf.write(textArea.getText()); buf.close(); // 设定状态栏为未修改 stateBar.setText("未修改"); } catch(IOException e) { JOptionPane.showMessageDialog(null, e.toString(), "写入文件失败", JOptionPane.ERROR_MESSAGE); } } } private void saveFileAs() { // 显示文件对话框 int option = fileChooser.showSaveDialog(null); // 如果确认选取文件 if(option == JFileChooser.APPROVE_OPTION) { // 取得选择的文件 File file = fileChooser.getSelectedFile(); // 在标题栏上设定文件名称 setTitle(file.toString()); try { // 建立文件 file.createNewFile(); // 进行文件保存 saveFile(); } catch(IOException e) { JOptionPane.showMessageDialog(null, e.toString(), "无法建立新文件", JOptionPane.ERROR_MESSAGE); } } } private void closeFile() { // 是否已保存文件 if(isCurrentFileSaved()) { // 释放窗口资源,而后关闭程序 dispose(); } else { int option = JOptionPane.showConfirmDialog( null, "文件已修改,是否保存?", "保存文件?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null); switch(option) { case JOptionPane.YES_OPTION: saveFile(); break; case JOptionPane.NO_OPTION: dispose(); } } } private void cut() { textArea.cut(); stateBar.setText("已修改"); popUpMenu.setVisible(false); } private void copy() { textArea.copy(); popUpMenu.setVisible(false); } private void paste() { textArea.paste(); stateBar.setText("已修改"); popUpMenu.setVisible(false); } private void processTextArea() { stateBar.setText("已修改"); } public static void main(String[] args) { new JNotePadUI(); } }
Java实现一个简单的记事本应用,你可以使用Swing或JavaFX库来构建GUI界面,以及文件I/O操作来读写文本文件。以下是一个基础的Swing实现的简单例子: ```java import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileWriter; import java.io.IOException; public class SimpleNotePad { private JFrame frame; private JTextArea textArea; private JButton saveButton; public static void main(String[] args) { EventQueue.invokeLater(() -> { try { SimpleNotePad window = new SimpleNotePad(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } }); } public SimpleNotePad() { initialize(); } private void initialize() { frame = new JFrame("Simple Note Pad"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(800, 600); frame.setLocationRelativeTo(null); JPanel panel = new JPanel(new BorderLayout()); frame.getContentPane().add(panel); textArea = new JTextArea(); textArea.setEditable(true); panel.add(textArea, BorderLayout.CENTER); saveButton = new JButton("Save"); saveButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String text = textArea.getText(); try { saveToFile(text); } catch (IOException ex) { JOptionPane.showMessageDialog(frame, "Failed to save file.", "Error", JOptionPane.ERROR_MESSAGE); } } }); panel.add(saveButton, BorderLayout.SOUTH); } private void saveToFile(String text) throws IOException { FileWriter writer = new FileWriter("notes.txt", true); // 'true' for appending to the file, else it will overwrite writer.write(text); writer.close(); } } ``` 在这个例子中,我们创建了一个JFrame窗口,包含一个JTextArea用于显示和编辑文本,以及一个JButton用于保存内容。当用户点击保存按钮时,会获取JTextArea中的文本并尝试将其写入到名为"notes.txt"的文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值