【超详细】如何使用Java Swing开发一个记事本

如何使用Java开发一个记事本?

一、需求分析

我们需要哪些需求呢?

首先第一个问题,就是关于记事本的用法,我们一般情况下使用记事本都是处理一些简单的问题,所以一个占满整个窗口的文本框就再合适不过了。参考Windows的记事本,我们可以发现,我们还需要一个菜单栏,来装载记事本的核心功能。

1、文件菜单

文件菜单一般包含新建、打开、保存、退出等功能。这些功能一般都需要一定的条件语句执行,不然会导致用户的编辑内容丢失。

2、编辑菜单

在这个菜单下一般集成复制粘贴、查找替换、撤销重做等功能。

3、查看菜单

我在这里放的是字数统计和字体大小设定。有余力可以添加更多的功能。

4、关于菜单

这个菜单就放一些作者信息之类的,不赘述了。

二、详细功能设计

这里主要是对整个记事本的详细开发记录,包括每个功能的用法以及代码

在这里先贴上我们需要用到的包

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.undo.UndoManager;

1、界面设计

为什么把界面放在最开始的地方讲呢?讲点题外话,在一个面向用户群体的大项目的开始,一般都是需求和UI最先对接,而后才是前后端算法开始施展拳脚。所以回到记事本的开发,我们需要使用JavaFX或者Java Swing来开发这个界面。虽然说使用Java开发界面挺扯淡的,但是秉着学习的精神,还是和大家讲讲。在这里我们使用Java Swing进行开发。

我们创建一个Notepad类,使用了ActionListener这个接口。这个接口的作用就是使得整个界面是可被键盘鼠标所响应的。记得在类里面写一个actionPerformed的方法,实现这个接口。我们稍后会用到。

然后就是定义一个窗口,一个文本域,一个菜单栏。并在构造方法里面实现他们。

我们需要一个带滚动条的文本域,而且需要设置好文本的大小以及字体,一样在类中创建font私有变量设置字体大小(这样设置主要是后面可以比较好修改文字大小)。

接着我们定义一下菜单栏的内容,并且设置在菜单栏上。

然后给每个菜单设置必要的功能按键,一样,我们定义一大串的菜单项,并添加至指定菜单项就OK啦!(菜单的一大串都是英文,非常好辨认,就不细讲了)。如果嫌不美观的话,可以选择另开一个方法**frameSetting()**将这些琐碎的东西全部扔进去(这部分代码将在界面响应部分给出)。

这样,我们一个基本的界面就出来了。

public class Notepad implements ActionListener {
     
	private JFrame frame = new JFrame("无标题 - 记事本");
	private JTextArea tea = new JTextArea();
    private JMenuBar jmb = new JMenuBar();
    private int fonts = 20; // 字体大小
    // 菜单栏内容
    JMenu fileMenu, editMenu, viewMenu, helpMenu;
    // “文件”的菜单项
	JMenuItem fileMenu_New, fileMenu_Open, fileMenu_Save, fileMenu_SaveAs, fileMenu_Exit;
	// “编辑”的菜单项
	JMenuItem editMenu_Undo, editMenu_Redo, editMenu_Cut, editMenu_Copy, editMenu_Paste, editMenu_Delete, editMenu_All,
			editMenu_Find, editMenu_Replace, editMenu_Coding;
	// “查看”的菜单项
	JMenuItem viewMenu_Statistics, viewMenu_Style;
	// “帮助”的菜单项
	JMenuItem helpMenu_About;
    // 构造方法
    public Notepad() {
     
        // 菜单栏内容
		fileMenu = new JMenu("文件(F)");
		editMenu = new JMenu("编辑(E)");
		viewMenu = new JMenu("查看(V)");
		helpMenu = new JMenu("帮助(H)");
        // 菜单项详细设置
        
		// 菜单栏内容注入菜单栏
		jmb.add(fileMenu);
		jmb.add(editMenu);
		jmb.add(viewMenu);
		jmb.add(helpMenu);
        
        // 窗口排布
        tea.requestFocus();
		frame.setJMenuBar(jmb);
		// 文字编辑界面的设置
		tea.setLineWrap(true);// 自动换行
		JScrollPane jsp = new JScrollPane(tea);// 滚动窗口面板
		frame.add(jsp);
		tea.setFont(new Font("宋体", Font.PLAIN, fonts));
        // 窗口运行设置
		frame.setSize(800, 600);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}
    
    @Override
	public void actionPerformed(ActionEvent e) {
     
		
	}
    //main方法
	public static void main(String[] args) {
     
		Notepad note = new Notepad();
	}
}

界面效果如下:

【超详细】如何使用Java Swing开发一个记事本_第1张图片

2、界面响应

一个大项目的开始,不仅仅是界面的设计,而且还有界面的交互逻辑。这个也是UI部分需要完成的,所以我们把这个东西放在这里讲。

界面的响应不仅仅是鼠标的点击,还要包括我们常用的键盘快捷键,例如复制粘贴Ctrl+C/V,保存撤销Ctrl+S/Z……这些快捷键太多了,不细讲,就讲一些比较不易理解的地方。

还记得上节的界面详细设计的方法吗?现在就给出来,顺带讲讲不易理解的问题。

菜单栏的默认快捷键就是Alt+*,所以我们直接设置栏目的快捷键字母就OK了。

第二是菜单子项的快捷键,这个快捷键参考了Windows记事本和一些其他文本编辑软件,尽量保证操作不会有太大差别。

设置方法:菜单项.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_快捷键字母, 需要组合的控制键))。

在这里解释一下最后的数字和控制键的关系:0表示不需要,1表示与Shift组合,2表示与Ctrl组合,3表示与Ctrl+Shift组合。

最后,我们需要给它们加上监听,不然设置的快捷键是不会生效的。

private void frameSetting() {
     
		// 文件菜单
		fileMenu.setMnemonic('F');// 设置快捷键ALT+F
		fileMenu_New = new JMenuItem("新建");
		fileMenu_New.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 2));
		fileMenu_New.addActionListener(this);
		fileMenu_Open = new JMenuItem("打开...");
		fileMenu_Open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 2));
		fileMenu_Open.addActionListener(this);
		fileMenu_Save = new JMenuItem("保存");
		fileMenu_Save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 2));
		fileMenu_Save.addActionListener(this);
		fileMenu_SaveAs = new JMenuItem("另存为...");
		fileMenu_SaveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 3));
		fileMenu_SaveAs.addActionListener(this);
		fileMenu_Exit = new JMenuItem("退出");
		fileMenu_Exit.addActionListener(this);
		// 编辑菜单
		editMenu.setMnemonic('E');// 设置快捷键ALT+E
		editMenu_Undo = new JMenuItem("撤销");
		editMenu_Undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, 2));
		editMenu_Undo.addActionListener(this);
		editMenu_Redo = new JMenuItem("重做");
		editMenu_Redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, 2));
		editMenu_Redo.addActionListener(this);
		editMenu_Cut = new JMenuItem("剪切");
		editMenu_Cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, 2));
		editMenu_Cut.addActionListener(this);
		editMenu_Copy = new JMenuItem("复制");
		editMenu_Copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 2));
		editMenu_Copy.addActionListener(this);
		editMenu_Paste = new JMenuItem("粘贴");
		editMenu_Paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, 2));
		editMenu_Paste.addActionListener(this);
		editMenu_Delete = new JMenuItem("删除");
		editMenu_Delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
		editMenu_Delete.addActionListener(this);
		editMenu_All = new JMenuItem("全选");
		editMenu_All.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 2));
		editMenu_All.addActionListener(this);
		editMenu_Find = new JMenuItem("查找");
		editMenu_Find.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, 2));
		editMenu_Find.addActionListener(this);
		editMenu_Replace = new JMenuItem("替换...");
		editMenu_Replace.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, 2));
		editMenu_Replace.addActionListener(this);
		editMenu_Coding = new JMenuItem("修改编码类型");
		editMenu_Coding.addActionListener(this);
		// 查看菜单
		viewMenu.setMnemonic('V');// 设置快捷键ALT+V
		viewMenu_Statistics = new JMenuItem("字数统计");
		viewMenu_Statistics.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_J, 2));
		viewMenu_Statistics.addActionListener(this);
		viewMenu_Style = new JMenuItem("字体大小");
		viewMenu_Style.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, 2));
		viewMenu_Style.addActionListener(this);
		// 帮助菜单
		helpMenu.setMnemonic('H');// 设置快捷键ALT+H
		helpMenu_About = new JMenuItem("关于");
		helpMenu_About.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 3));
		helpMenu_About.addActionListener(this);
		//添加到菜单
		fileMenu.add(fileMenu_New);
		fileMenu.addSeparator();
		fileMenu.add(fileMenu_Open);
		fileMenu.add(fileMenu_Save);
		fileMenu.add(fileMenu_SaveAs);
		fileMenu.addSeparator();
		fileMenu.add(fileMenu_Exit);
		
		editMenu.add(editMenu_Undo);
		editMenu.add(editMenu_Redo);
		editMenu.addSeparator();
		editMenu.add(editMenu_Cut);
		editMenu.add(editMenu_Copy);
		editMenu.add(editMenu_Paste);
		editMenu.add(editMenu_Delete);
		editMenu.add(editMenu_All);
		editMenu.addSeparator();
		editMenu.add(editMenu_Find);
		editMenu.add(editMenu_Replace);
		editMenu.add(editMenu_Coding);
		
		viewMenu.add(viewMenu_Statistics);
		viewMenu.add(viewMenu_Style);
		
		helpMenu.add(helpMenu_About);
	}

3、界面功能

终于到了核心的功能环节了,在这个环节,我们的代码会显得有亿点乱,不过不要着急,我会带着大家一步步走。

(1)保存于关闭的逻辑问题

我们之前也讲过,不能丢失用户的数据,所以我们需要检测打开软件后,文本框是否被修改,或者说,文本框有没有字符,来判断是否需要提示用户保存文件。所以我们还是需要一个监听,监听什么呢?监听文本框有没有历史记录,但是这样子实现起来有点复杂,秉承能简则简的原则,我们使用一个if语句去判断文本框是否为空,为空则直接退出,不为空就提示保存。

看似很完美的解决方案,但是我们是否忽视了一个问题,如果这个文件用户保存过了,文本框也有文字啊,要是没有修改就点了关闭,按照判空原则,这时我们还要像新建文件时一样再次提醒?这就太蠢了,于是我们就需要一个更加厉害的判断方法,具体的判断方式可以看图,我就不细讲了,图能解释的程度比文字高。另外其他的功能实现以及逻辑都在下图,在这里就不一一赘述了:

【超详细】如何使用Java Swing开发一个记事本_第2张图片

对于退出保存逻辑部分功能的实现,我还是将代码贴上

//先前需要一个flag变量,存储当前文件是否存在源文件:true,没有;false,有(也不知道当初是不是脑子抽了,弄了这样反的判断)
private boolean flag = true;
private String txt = "";
private File f;
//在构造方法上最后一行加上这个
		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//意思是关闭按钮失效
public void Exit() {
     
		String tst = new String(tea.getText());
		if (!flag) {
      // 如果有源文件
			if (txt.equals(tst)) {
      // 判断文本是否有改动
				System.exit(0);
			} else {
      // 有改动
				int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存",
						JOptionPane.YES_NO_CANCEL_OPTION);
				if (i == JOptionPane.OK_OPTION) {
     
					write();
				} else if (i == JOptionPane.NO_OPTION) {
     
					System.exit(0);
				}
			}
		} else {
      // 无源文件
			if (txt.equals(tst)) {
      // 判断文本是否有改动
				System.exit(0);
			} else {
      // 有改动
				int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存",
						JOptionPane.YES_NO_CANCEL_OPTION);
				if (i == JOptionPane.OK_OPTION) {
     
					SaveF rep = new SaveF(); //调用保存类
					f = rep.f;
					write();
				} else if (i == JOptionPane.NO_OPTION) {
     
					System.exit(0);
				}
			}
		}
	}
//另外,在main上加上这么几行,保证关闭按钮的正常响应
// 关闭的时候询问是否保存文件
		note.frame.addWindowListener(new WindowAdapter() {
     
			public void windowClosing(WindowEvent e) {
     
				note.Exit();
			}
		});

(2)保存功能

刚才的代码是运行不了的,因为我还没给你们写入和保存的代码,对于这个功能,我选择了重新写两个类。一个类是关于保存的具体操作,另一个是保存的后缀名问题。第二个类继承了文件对话框FileFilter,并写入后缀名的选择。

class T1 extends FileFilter {
      // 继承文件对话框的并添加文件筛选后缀名
	String ends; // 文件后缀
	String description; // 文件描述文字
	public T1(String ends, String description) {
      // 构造函数
		this.ends = ends; // 设置文件后缀
		this.description = description; // 设置文件描述文字
	}
	@Override
	// 只显示符合扩展名的文件,目录全部显示
	public boolean accept(File file) {
     
		if (file.isDirectory())
			return true;
		String fileName = file.getName();
		if (fileName.toUpperCase().endsWith(this.ends.toUpperCase()))
			return true;
		return false;
	}
	@Override
	// 返回这个扩展名过滤器的描述
	public String getDescription() {
     
		if (this.description == "所有文件")
			this.description = "文件";
		return this.description;
	}
	// 返回这个扩展名过滤器的扩展名
	public String getEnds() {
     
		return this.ends;
	}
}
class SaveF {
      // 保存文件类
	File f;
	JFileChooser rep = new JFileChooser("%homepath%");
	T1 txtFilter = new T1(".txt", "文件文档 (*.txt)");
	T1 txtFilter1 = new T1(".ini", "配置文件 (*.ini)");
	SaveF() {
     
		rep.addChoosableFileFilter(txtFilter);
		rep.addChoosableFileFilter(txtFilter1);
		int returnVal = rep.showDialog(null, "保存");
		if (returnVal == JFileChooser.APPROVE_OPTION) {
      // 在文件选择后再执行保存命令
			if (!(rep.getFileFilter().getDescription() == "所有文件")) {
     
				File file = rep.getSelectedFile(); // 获得文件名
				// 获得被选中的过滤器
				T1 filter = (T1) rep.getFileFilter();
				// 获得过滤器的扩展名
				String ends = filter.getEnds();
				File newFile = null;
				if (file.getAbsolutePath().toUpperCase().endsWith(ends.toUpperCase())) {
     
					// 如果文件是以选定扩展名结束的,则使用原名
					newFile = file;
					System.out.println("保存路径:" + newFile.getAbsolutePath());
					f = new File(newFile.getAbsolutePath());
				} else {
     
					// 否则加上选定的扩展名
					newFile = new File(file.getAbsolutePath() + ends);
					System.out.println("保存路径:" + newFile.getAbsolutePath());
					f = new File(newFile.getAbsolutePath());
				}
			} else {
     
				f = rep.getSelectedFile();
				System.out.println("保存路径:" + f);
			}
		}
	}
}

但是光有这个还不够,我还在Notepad主类里面写入了write方法,这个方法是纯写入文件的。

对了,有件事情忘了说,我对这个软件加入了ANSI和UTF-8两种编码格式支持,所以保存的时候是根据你之前在编辑菜单的修改编码来决定你的保存编码,这些都集成在write方法里面了。

// 我们还需要在主类里面加上以下变量
private String encoding = "UTF-8";
public void write() {
     
		if (f.exists()) {
     
			int i = JOptionPane.showConfirmDialog(null, "此位置已出现重名文件,是否保存该文件并删除之前文件", "确认保存",
					JOptionPane.YES_NO_OPTION);
			if (i == JOptionPane.OK_OPTION) {
     
				try {
     
					if (encoding.equals("UTF-8")) {
     
						BufferedWriter fos = new BufferedWriter(
								new OutputStreamWriter(new FileOutputStream(f), encoding));
						System.out.println("已成功删除已有文件并保持当前文件");
						fos.write(tea.getText());
						System.out.println("22222");
						fos.close();
					} else {
     
						Writer fos = new OutputStreamWriter(new FileOutputStream(f, false), "GB2312");
						System.out.println("已成功删除已有文件并保持当前文件");
						fos.write(tea.getText());
						fos.close();
					}
				} catch (Exception e) {
     
					e.printStackTrace();
				}
			}
		} else
			try {
     
				if (encoding.equals("UTF-8")) {
     
					BufferedWriter fos = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), encoding));
					System.out.println("已成功删除已有文件并保持当前文件");
					fos.write(tea.getText());
					System.out.println("22222");
					fos.close();
				} else {
     
					Writer fos = new OutputStreamWriter(new FileOutputStream(f, false), "GB2312");
					System.out.println("已成功删除已有文件并保持当前文件");
					fos.write(tea.getText());
					fos.close();
				}
			} catch (Exception e) {
     
				e.printStackTrace();
			}
	}

(3)打开 / 新建功能

像上一节讲到的,我们使用了两种编码方式供用户选择,所以我们针对打开的操作也是分为了两个不同的过程;而对于新建,也是需要和关闭程序一样,做到判断用户修改文字的问题,但是我们并不用重新写一遍,而是通过判断后选择性调用Exit方法。

// 读取命令
	public String read() {
       //ANSI读取
		String temp = "";
		try {
     
			FileInputStream fis = new FileInputStream(f.getAbsolutePath());
			byte[] b = new byte[1024];
			while (true) {
     
				int num = fis.read(b);
				if (num == -1)
					break;
				temp = temp + new String(b, 0, num);
			}
			fis.close();
		} catch (Exception e1) {
     
			e1.printStackTrace();
		}
		return temp;
	}
	@SuppressWarnings("resource")
	public String read(String encoding) throws IOException {
      //UTF-8读取
		File file = new File(f.getAbsolutePath());
		String message = "";// 获取文件内容
		if (file.isFile() && file.exists()) {
     
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding));
			String buff;
			while ((buff = br.readLine()) != null) {
     
				message = message + buff + "\n";
			}
		}
		return message;
	}

// 新建命令
public void NewFile() {
     
		frame.dispose();
		Notepad note = new Notepad();
		// 关闭的时候询问是否保存文件
		note.frame.addWindowListener(new WindowAdapter() {
     
			public void windowClosing(WindowEvent e) {
     
				note.Exit();
			}
		});
	}

到这里,我们一些比较繁杂的工作就做完了,接下来的问题都比较简单了

(4)其他功能的实现

其实程序写到这了,你还是发现程序运行不起来,不要慌,只是你还没设置菜单的监听事件怎么运行。还记得一开始我说的需要实现的一个方法吗?

就是这个:

@Override
	public void actionPerformed(ActionEvent e) {
     
		
	}

我们就把响应的操作使用if else语句实现出来,虽然这个方式感觉代码瞬间不简洁了,你们有能力可以使用switch方式进行,在这里就不实现了

public void actionPerformed(ActionEvent e) {
     
		String commamd = e.getActionCommand();
		System.out.println("执行的命令->" + commamd); // 在命令行界面显示点击菜单所执行的命令
		// “新建”事件
		if ("新建".equals(commamd)) {
     
			String tst = new String(tea.getText());
			if (!flag) {
      // 如果有源文件
				if (txt.equals(tst)) {
      // 无改动
					flag = true;
					NewFile();
				} else {
      // 有改动
					int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存",
							JOptionPane.YES_NO_CANCEL_OPTION);
					if (i == JOptionPane.OK_OPTION) {
     
						write();
						flag = true;
						NewFile();
					} else if (i == JOptionPane.NO_OPTION) {
     
						flag = true;
						NewFile();
					}
				}
			} else {
      // 无源文件
				if (txt.equals(tst)) {
      // 无改动
					flag = true;
					NewFile();
				} else {
      // 有改动
					int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存",
							JOptionPane.YES_NO_CANCEL_OPTION);
					if (i == JOptionPane.OK_OPTION) {
     
						SaveF rep = new SaveF();
						f = rep.f;
						flag = true;
						write();
						NewFile();
					} else if (i == JOptionPane.NO_OPTION) {
     
						flag = true;
						NewFile();
					}
				}
			}
			// “打开”事件
		} else if ("打开...".equals(commamd)) {
     
			JFileChooser rep = new JFileChooser("%homepath%");
			rep.setDialogType(JFileChooser.OPEN_DIALOG);
			int returnVal = rep.showOpenDialog(null);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
     
				f = rep.getSelectedFile();
				frame.setTitle(f.getName());
				sumT.setSize(250, 150);
				sumT.setLayout(new GridLayout(1, 2));
				sumT.setLocationRelativeTo(null);
				read_encod1.setFont(new Font("微软雅黑", Font.BOLD, 20));
				read_encod2.setFont(new Font("微软雅黑", Font.BOLD, 20));
				sumT.add(read_encod1);
				sumT.add(read_encod2);
				sumT.setVisible(true);
			}
			// “保存”事件
		} else if ("保存".equals(commamd)) {
     
			if (flag) {
     
				SaveF rep = new SaveF();
				f = rep.f;
				flag = false;
			}
			write();
			frame.setTitle(f.getName());
			txt = tea.getText();
			// “另存为”事件
		} else if ("另存为...".equals(commamd)) {
     
			SaveF rep = new SaveF();
			f = rep.f;
			flag = false;
			write();
			frame.setTitle(f.getName());
			// 其他功能事件
		} else if ("退出".equals(commamd)) {
     
			Exit();
		} else if ("撤销".equals(commamd)) {
     
			if(undoManager.canUndo()) {
      
				undoManager.undo();
			}
		} else if ("重做".equals(commamd)) {
     
			if(undoManager.canRedo()) {
      
				undoManager.redo();
			}
		} else if ("剪切".equals(commamd)) {
     
			value = tea.getText();
			tea.cut();
		} else if ("复制".equals(commamd)) {
     
			tea.copy();
		} else if ("粘贴".equals(commamd)) {
     
			value = tea.getText();
			tea.paste();
		} else if ("删除".equals(commamd)) {
     
			value = tea.getText();
			tea.replaceSelection(null);
		} else if ("全选".equals(commamd)) {
     
			tea.selectAll();
		}
		// 查找事件
		else if ("查找".equals(commamd)) {
     
			value = tea.getText();
			find.add(jtf, BorderLayout.CENTER);
			find.add(jb, BorderLayout.SOUTH);
			find.setSize(250, 100);
			find.setLocationRelativeTo(null);
			find.setVisible(true);
			find.setResizable(false);
			find.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			// 替换事件
		} else if ("替换...".equals(commamd)) {
     
			value = tea.getText();
			GridLayout gl = new GridLayout(3, 3);
			jl1.setFont(new Font("微软雅黑", Font.BOLD, 13));
			jl2.setFont(new Font("微软雅黑", Font.BOLD, 13));
			rep.setLayout(gl);
			rep.add(jl1);
			rep.add(jtf);
			rep.add(jb);
			rep.add(jl2);
			rep.add(jt);
			rep.add(jbt);
			rep.add(jl3);
			rep.add(jl4);
			rep.add(jba);
			rep.setSize(500, 120);
			rep.setLocationRelativeTo(null);
			rep.setVisible(true);
			rep.setResizable(false);
			rep.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			// 关于选项卡
		} else if ("关于".equals(commamd)) {
     
			JDialog dia = new JDialog(frame, "关于Notepad- -");
			dia.setSize(250, 160);
			dia.setResizable(false);
			JLabel l = new JLabel("   记事本(Notepad- -)
 JavaSwing设计

 &emsp设计者:Equent
  组员:Summerboy、逸&风"
); l.setFont(new Font("微软雅黑", Font.BOLD, 15)); dia.add(l, BorderLayout.CENTER); dia.setLocationRelativeTo(null); dia.setVisible(true); dia.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); // 查找&替换 的查找功能事件 } else if ("开始".equals(commamd) || "下一个".equals(commamd)) { String temp = jtf.getText(); int s = value.indexOf(temp, start); if (value.indexOf(temp, start) != -1) { tea.setSelectionStart(s); tea.setSelectionEnd(s + temp.length()); start = s + 1; jb.setText("下一个"); } else { JOptionPane.showMessageDialog(find, "查找完毕!", "提示", 0); find.dispose(); } // 替换的替换功能事件 } else if ("替换为".equals(commamd)) { String temp = jtf.getText(); int s = value.indexOf(temp, start); if (value.indexOf(temp, start) != -1) { tea.setSelectionStart(s); tea.setSelectionEnd(s + temp.length()); tea.setSelectedTextColor(Color.GREEN); start = s + 1; tea.replaceSelection(jt.getText()); } else { JOptionPane.showMessageDialog(find, "查找完毕!", "提示", 0); find.dispose(); } } else if ("全部替换".equals(commamd)) { String temp = tea.getText(); temp = temp.replaceAll(jtf.getText(), jt.getText()); tea.setText(temp); // 字数统计事件 } else if ("字数统计".equals(commamd)) { String s = tea.getText(); int alphaCount = 0; int digitCount = 0; int otherCount = 0; for (int i = 0; i < s.length(); ++i) { if (Character.isDigit(s.charAt(i))) digitCount++; else if (Character.isAlphabetic(s.charAt(i))) alphaCount++; else otherCount++; } int allCount = alphaCount + digitCount + otherCount; JDialog sumF = new JDialog(frame, "字数统计"); sumF.setSize(150, 200); sumF.setLayout(new GridLayout(4, 1)); sumF.setLocationRelativeTo(null); JLabel alpha = new JLabel(" 字数: " + alphaCount); JLabel digit = new JLabel(" 数字: " + digitCount); JLabel other = new JLabel(" 其它: " + otherCount); JLabel all = new JLabel(" 总计: " + allCount); alpha.setFont(new Font("微软雅黑", Font.BOLD, 13)); digit.setFont(new Font("微软雅黑", Font.BOLD, 13)); other.setFont(new Font("微软雅黑", Font.BOLD, 13)); all.setFont(new Font("微软雅黑", Font.BOLD, 13)); sumF.add(alpha); sumF.add(digit); sumF.add(other); sumF.add(all); sumF.setVisible(true); sumF.setResizable(false); // 修改字体大小 } else if ("字体大小".equals(commamd)) { diaf.setSize(230, 100); fnts.setFont(new Font("微软雅黑", Font.PLAIN, 15)); diaf.add(fnts, BorderLayout.CENTER); diaf.add(conf, BorderLayout.SOUTH); diaf.setLocationRelativeTo(null); diaf.setVisible(true); diaf.setResizable(false); diaf.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); } else if ("确定".equals(commamd)) { //字体修改 String fnt = fnts.getText(); int fs = Integer.parseInt(fnt); tea.setFont(new Font("宋体", Font.PLAIN, fs)); System.out.println("字体修改成功!"); diaf.dispose(); }else if ("修改编码类型".equals(commamd)) { encod.setSize(230, 120); fnts1.setFont(new Font("微软雅黑", Font.BOLD, 15)); jwarn.setFont(new Font("微软雅黑", Font.PLAIN, 15)); encod.add(jwarn, BorderLayout.NORTH); encod.add(fnts1, BorderLayout.CENTER); encod.add(conf1, BorderLayout.SOUTH); encod.setLocationRelativeTo(null); encod.setVisible(true); encod.setResizable(false); encod.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); } else if ("确定修改".equals(commamd)) { //编码修改 String new_enconing = ((String) fnts1.getText()); if (new_enconing.compareTo("UTF-8") == 0 || new_enconing.compareTo("ANSI") == 0) { encoding = fnts1.getText(); System.out.println(encoding); encod.dispose(); System.out.println("成功修改编码至" + fnts1.getText()); } else { JOptionPane.showMessageDialog(encod, "输入编码类型有误(区分大小写)或不支持该编码", "提示", 0); } } else if ("UTF-8".equals(commamd)) { encoding = "UTF-8"; try { res = read("UTF-8"); } catch (IOException e1) { e1.printStackTrace(); } sumT.dispose(); flag = false; value = res; tea.setText(res); txt = tea.getText(); } else if ("ANSI".equals(commamd)) { encoding = "ANSI"; res = read(); sumT.dispose(); flag = false; value = res; tea.setText(res); txt = tea.getText(); } }

在这里你会发现很多变量没有定义,不要慌,我们一样在类中定义私有变量

	private String res = ""; // 命令行界面的输出结果参数
	private JTextField jtf = new JTextField(15);// 查找输入框
	private JTextField jt = new JTextField(15);// 替换输入框
	private String value;
	private int start = 0;
	private JTextField fnts = new JTextField(15);
	private JTextField fnts1 = new JTextField(15);
	private JLabel jl1 = new JLabel("    查找内容:");
	private JLabel jl2 = new JLabel("    替换为:");
	private JLabel jl3 = new JLabel();
	private JLabel jl4 = new JLabel();
	private JLabel jwarn = new JLabel("  目前只支持ANSI和UTF-8编码");
	UndoManager undoManager = new UndoManager();
	// 对话框和控件
	private JButton jb = new JButton("开始");
	private JButton jbt = new JButton("替换为");
	private JButton jba = new JButton("全部替换");
	private JButton conf = new JButton("确定");
	private JButton conf1 = new JButton("确定修改");
	private JDialog find = new JDialog(frame, "查找");
	private JDialog rep = new JDialog(frame, "替换");
	private JDialog diaf = new JDialog(frame, "请输入字号");
	private JDialog encod = new JDialog(frame, "请输入编码类型");
	private JButton read_encod1 = new JButton("UTF-8");
	private JButton read_encod2 = new JButton("ANSI");
	private JDialog sumT = new JDialog(frame, "请选择打开文件的编码形式");

(5)善后工作

现在你的记事本跑起来了么?如果跑起来了,恭喜!你离成功不远了。你再仔细想想,我们还能给这个记事本添加什么功能?如果把你自己想象成用户,你在word或者其他编辑软件里面是不是经常打开右键菜单?

右键菜单是不是忘了?这就是我们的善后工作!

//在主类中定义如下菜单项,它们就是右键菜单
JPopupMenu popupMenu;
	JMenuItem popupMenu_Undo, popupMenu_Redo, popupMenu_Cut, popupMenu_Copy, popupMenu_Paste, popupMenu_Delete,
			popupMenu_All;
//然后在frameSetting方法中加入如下代码
		// 创建右键弹出菜单
		popupMenu = new JPopupMenu();
		popupMenu_Undo = new JMenuItem("撤销");
		popupMenu_Undo.addActionListener(this);
		popupMenu_Redo = new JMenuItem("重做");
		popupMenu_Redo.addActionListener(this);
		popupMenu_Cut = new JMenuItem("剪切");
		popupMenu_Cut.addActionListener(this);
		popupMenu_Copy = new JMenuItem("复制");
		popupMenu_Copy.addActionListener(this);
		popupMenu_Paste = new JMenuItem("粘贴");
		popupMenu_Paste.addActionListener(this);
		popupMenu_Delete = new JMenuItem("删除");
		popupMenu_Delete.addActionListener(this);
		popupMenu_All = new JMenuItem("全选");
		popupMenu_All.addActionListener(this);
		// 向右键菜单添加菜单项和分隔符
		popupMenu.add(popupMenu_Undo);
		popupMenu.add(popupMenu_Redo);
		popupMenu.addSeparator();
		popupMenu.add(popupMenu_Cut);
		popupMenu.add(popupMenu_Copy);
		popupMenu.add(popupMenu_Paste);
		popupMenu.add(popupMenu_Delete);
		popupMenu.addSeparator();
		popupMenu.add(popupMenu_All);
//然后,在构造方法中写入右键菜单的监听事件,在菜单栏内容之后添加
		// 文本编辑区注册右键菜单事件
		tea.addMouseListener(new MouseAdapter() {
     
			public void mousePressed(MouseEvent e) {
     
				if (e.isPopupTrigger())// 返回此鼠标事件是否为该平台的弹出菜单触发事件
				{
     
					popupMenu.show(e.getComponent(), e.getX(), e.getY());// 在组件调用者的坐标空间中的位置 X、Y 显示弹出菜单
				}
				tea.requestFocus();// 编辑区获取焦点
			}
			public void mouseReleased(MouseEvent e) {
     
				if (e.isPopupTrigger())// 返回此鼠标事件是否为该平台的弹出菜单触发事件
				{
     
					popupMenu.show(e.getComponent(), e.getX(), e.getY());// 在组件调用者的坐标空间中的位置 X、Y 显示弹出菜单
				}
				tea.requestFocus();// 编辑区获取焦点
			}
		});// 文本编辑区注册右键菜单事件结束

这样,你的程序就算是真正的写完了!

你跑了一下程序,发现确实可以运行起来了!但是你总觉得哪里不对劲,是吧,我也觉得。

这界面好丑啊

不慌,我们换成Windows的风格就完事啦!

同样,我们在main的开头添加如下代码,让界面风格来个大变样!

// 生成Windows风格的UI界面
		try {
     
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
				| UnsupportedLookAndFeelException e) {
     
			e.printStackTrace();
		};

这时,你就会发现!这界面终于像个样子了!

【超详细】如何使用Java Swing开发一个记事本_第3张图片

三、完整的详细代码

懒癌是不需要拯救的,于是我也准备了一份完整的代码,供大家直接应付了事

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.undo.UndoManager;

public class Notepad implements ActionListener {
     
	private JFrame frame = new JFrame("无标题 - 记事本");
	private JTextArea tea = new JTextArea();
	private JMenuBar jmb = new JMenuBar();
	private int fonts = 20; // 字体大小
	// 先前需要一个flag变量,存储当前文件是否存在源文件:true,没有;false,有(也不知道当初是不是脑子抽了,弄了这样反的判断)
	private boolean flag = true;
	private String txt = "";
	private File f;
	private String encoding = "UTF-8";

	private String res = ""; // 命令行界面的输出结果参数
	private JTextField jtf = new JTextField(15);// 查找输入框
	private JTextField jt = new JTextField(15);// 替换输入框
	private String value;
	private int start = 0;
	private JTextField fnts = new JTextField(15);
	private JTextField fnts1 = new JTextField(15);
	private JLabel jl1 = new JLabel("    查找内容:");
	private JLabel jl2 = new JLabel("    替换为:");
	private JLabel jl3 = new JLabel();
	private JLabel jl4 = new JLabel();
	private JLabel jwarn = new JLabel("  目前只支持ANSI和UTF-8编码");
	UndoManager undoManager = new UndoManager();
	// 对话框和控件
	private JButton jb = new JButton("开始");
	private JButton jbt = new JButton("替换为");
	private JButton jba = new JButton("全部替换");
	private JButton conf = new JButton("确定");
	private JButton conf1 = new JButton("确定修改");
	private JDialog find = new JDialog(frame, "查找");
	private JDialog rep = new JDialog(frame, "替换");
	private JDialog diaf = new JDialog(frame, "请输入字号");
	private JDialog encod = new JDialog(frame, "请输入编码类型");
	private JButton read_encod1 = new JButton("UTF-8");
	private JButton read_encod2 = new JButton("ANSI");
	private JDialog sumT = new JDialog(frame, "请选择打开文件的编码形式");
	// 菜单栏内容
	JMenu fileMenu, editMenu, viewMenu, helpMenu;
	// “文件”的菜单项
	JMenuItem fileMenu_New, fileMenu_Open, fileMenu_Save, fileMenu_SaveAs, fileMenu_Exit;
	// “编辑”的菜单项
	JMenuItem editMenu_Undo, editMenu_Redo, editMenu_Cut, editMenu_Copy, editMenu_Paste, editMenu_Delete, editMenu_All,
			editMenu_Find, editMenu_Replace, editMenu_Coding;
	// “查看”的菜单项
	JMenuItem viewMenu_Statistics, viewMenu_Style;
	// “帮助”的菜单项
	JMenuItem helpMenu_About;

	// 在主类中定义如下菜单项,它们就是右键菜单
	JPopupMenu popupMenu;
	JMenuItem popupMenu_Undo, popupMenu_Redo, popupMenu_Cut, popupMenu_Copy, popupMenu_Paste, popupMenu_Delete,
			popupMenu_All;

	public Notepad() {
     
		// 菜单栏内容
		fileMenu = new JMenu("文件(F)");
		editMenu = new JMenu("编辑(E)");
		viewMenu = new JMenu("查看(V)");
		helpMenu = new JMenu("帮助(H)");
		// 菜单栏详细设置
		frameSetting();
		// 菜单栏内容注入菜单栏
		jmb.add(fileMenu);
		jmb.add(editMenu);
		jmb.add(viewMenu);
		jmb.add(helpMenu);

		tea.addMouseListener(new MouseAdapter() {
     
			public void mousePressed(MouseEvent e) {
     
				if (e.isPopupTrigger())// 返回此鼠标事件是否为该平台的弹出菜单触发事件
				{
     
					popupMenu.show(e.getComponent(), e.getX(), e.getY());// 在组件调用者的坐标空间中的位置 X、Y 显示弹出菜单
				}
				tea.requestFocus();// 编辑区获取焦点
			}

			public void mouseReleased(MouseEvent e) {
     
				if (e.isPopupTrigger())// 返回此鼠标事件是否为该平台的弹出菜单触发事件
				{
     
					popupMenu.show(e.getComponent(), e.getX(), e.getY());// 在组件调用者的坐标空间中的位置 X、Y 显示弹出菜单
				}
				tea.requestFocus();// 编辑区获取焦点
			}
		});// 文本编辑区注册右键菜单事件结束

		tea.requestFocus();
		frame.setJMenuBar(jmb);
		// 文字编辑界面的设置
		tea.setLineWrap(true);// 自动换行
		JScrollPane jsp = new JScrollPane(tea);// 滚动窗口面板
		frame.add(jsp);
		tea.setFont(new Font("宋体", Font.PLAIN, fonts));
		frame.setSize(800, 600);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);// 意思是关闭按钮失效
	}

	@Override
	public void actionPerformed(ActionEvent e) {
     
		String commamd = e.getActionCommand();
		System.out.println("执行的命令->" + commamd); // 在命令行界面显示点击菜单所执行的命令
		// “新建”事件
		if ("新建".equals(commamd)) {
     
			String tst = new String(tea.getText());
			if (!flag) {
      // 如果有源文件
				if (txt.equals(tst)) {
      // 无改动
					flag = true;
					NewFile();
				} else {
      // 有改动
					int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存",
							JOptionPane.YES_NO_CANCEL_OPTION);
					if (i == JOptionPane.OK_OPTION) {
     
						write();
						flag = true;
						NewFile();
					} else if (i == JOptionPane.NO_OPTION) {
     
						flag = true;
						NewFile();
					}
				}
			} else {
      // 无源文件
				if (txt.equals(tst)) {
      // 无改动
					flag = true;
					NewFile();
				} else {
      // 有改动
					int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存",
							JOptionPane.YES_NO_CANCEL_OPTION);
					if (i == JOptionPane.OK_OPTION) {
     
						SaveF rep = new SaveF();
						f = rep.f;
						flag = true;
						write();
						NewFile();
					} else if (i == JOptionPane.NO_OPTION) {
     
						flag = true;
						NewFile();
					}
				}
			}
			// “打开”事件
		} else if ("打开...".equals(commamd)) {
     
			JFileChooser rep = new JFileChooser("%homepath%");
			rep.setDialogType(JFileChooser.OPEN_DIALOG);
			int returnVal = rep.showOpenDialog(null);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
     
				f = rep.getSelectedFile();
				frame.setTitle(f.getName());
				sumT.setSize(250, 150);
				sumT.setLayout(new GridLayout(1, 2));
				sumT.setLocationRelativeTo(null);
				read_encod1.setFont(new Font("微软雅黑", Font.BOLD, 20));
				read_encod2.setFont(new Font("微软雅黑", Font.BOLD, 20));
				sumT.add(read_encod1);
				sumT.add(read_encod2);
				sumT.setVisible(true);
			}
			// “保存”事件
		} else if ("保存".equals(commamd)) {
     
			if (flag) {
     
				SaveF rep = new SaveF();
				f = rep.f;
				flag = false;
			}
			write();
			frame.setTitle(f.getName());
			txt = tea.getText();
			// “另存为”事件
		} else if ("另存为...".equals(commamd)) {
     
			SaveF rep = new SaveF();
			f = rep.f;
			flag = false;
			write();
			frame.setTitle(f.getName());
			// 其他功能事件
		} else if ("退出".equals(commamd)) {
     
			Exit();
		} else if ("撤销".equals(commamd)) {
     
			if (undoManager.canUndo()) {
     
				undoManager.undo();
			}
		} else if ("重做".equals(commamd)) {
     
			if (undoManager.canRedo()) {
     
				undoManager.redo();
			}
		} else if ("剪切".equals(commamd)) {
     
			value = tea.getText();
			tea.cut();
		} else if ("复制".equals(commamd)) {
     
			tea.copy();
		} else if ("粘贴".equals(commamd)) {
     
			value = tea.getText();
			tea.paste();
		} else if ("删除".equals(commamd)) {
     
			value = tea.getText();
			tea.replaceSelection(null);
		} else if ("全选".equals(commamd)) {
     
			tea.selectAll();
		}
		// 查找事件
		else if ("查找".equals(commamd)) {
     
			value = tea.getText();
			find.add(jtf, BorderLayout.CENTER);
			find.add(jb, BorderLayout.SOUTH);
			find.setSize(250, 100);
			find.setLocationRelativeTo(null);
			find.setVisible(true);
			find.setResizable(false);
			find.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			// 替换事件
		} else if ("替换...".equals(commamd)) {
     
			value = tea.getText();
			GridLayout gl = new GridLayout(3, 3);
			jl1.setFont(new Font("微软雅黑", Font.BOLD, 13));
			jl2.setFont(new Font("微软雅黑", Font.BOLD, 13));
			rep.setLayout(gl);
			rep.add(jl1);
			rep.add(jtf);
			rep.add(jb);
			rep.add(jl2);
			rep.add(jt);
			rep.add(jbt);
			rep.add(jl3);
			rep.add(jl4);
			rep.add(jba);
			rep.setSize(500, 120);
			rep.setLocationRelativeTo(null);
			rep.setVisible(true);
			rep.setResizable(false);
			rep.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			// 关于选项卡
		} else if ("关于".equals(commamd)) {
     
			JDialog dia = new JDialog(frame, "关于Notepad- -");
			dia.setSize(250, 160);
			dia.setResizable(false);
			JLabel l = new JLabel(
					"   记事本(Notepad- -)
 JavaSwing设计

 &emsp设计者:Equent
  组员:Summerboy、逸&风"
); l.setFont(new Font("微软雅黑", Font.BOLD, 15)); dia.add(l, BorderLayout.CENTER); dia.setLocationRelativeTo(null); dia.setVisible(true); dia.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); // 查找&替换 的查找功能事件 } else if ("开始".equals(commamd) || "下一个".equals(commamd)) { String temp = jtf.getText(); int s = value.indexOf(temp, start); if (value.indexOf(temp, start) != -1) { tea.setSelectionStart(s); tea.setSelectionEnd(s + temp.length()); start = s + 1; jb.setText("下一个"); } else { JOptionPane.showMessageDialog(find, "查找完毕!", "提示", 0); find.dispose(); } // 替换的替换功能事件 } else if ("替换为".equals(commamd)) { String temp = jtf.getText(); int s = value.indexOf(temp, start); if (value.indexOf(temp, start) != -1) { tea.setSelectionStart(s); tea.setSelectionEnd(s + temp.length()); tea.setSelectedTextColor(Color.GREEN); start = s + 1; tea.replaceSelection(jt.getText()); } else { JOptionPane.showMessageDialog(find, "查找完毕!", "提示", 0); find.dispose(); } } else if ("全部替换".equals(commamd)) { String temp = tea.getText(); temp = temp.replaceAll(jtf.getText(), jt.getText()); tea.setText(temp); // 字数统计事件 } else if ("字数统计".equals(commamd)) { String s = tea.getText(); int alphaCount = 0; int digitCount = 0; int otherCount = 0; for (int i = 0; i < s.length(); ++i) { if (Character.isDigit(s.charAt(i))) digitCount++; else if (Character.isAlphabetic(s.charAt(i))) alphaCount++; else otherCount++; } int allCount = alphaCount + digitCount + otherCount; JDialog sumF = new JDialog(frame, "字数统计"); sumF.setSize(150, 200); sumF.setLayout(new GridLayout(4, 1)); sumF.setLocationRelativeTo(null); JLabel alpha = new JLabel(" 字数: " + alphaCount); JLabel digit = new JLabel(" 数字: " + digitCount); JLabel other = new JLabel(" 其它: " + otherCount); JLabel all = new JLabel(" 总计: " + allCount); alpha.setFont(new Font("微软雅黑", Font.BOLD, 13)); digit.setFont(new Font("微软雅黑", Font.BOLD, 13)); other.setFont(new Font("微软雅黑", Font.BOLD, 13)); all.setFont(new Font("微软雅黑", Font.BOLD, 13)); sumF.add(alpha); sumF.add(digit); sumF.add(other); sumF.add(all); sumF.setVisible(true); sumF.setResizable(false); // 修改字体大小 } else if ("字体大小".equals(commamd)) { diaf.setSize(230, 100); fnts.setFont(new Font("微软雅黑", Font.PLAIN, 15)); diaf.add(fnts, BorderLayout.CENTER); diaf.add(conf, BorderLayout.SOUTH); diaf.setLocationRelativeTo(null); diaf.setVisible(true); diaf.setResizable(false); diaf.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); } else if ("确定".equals(commamd)) { // 字体修改 String fnt = fnts.getText(); int fs = Integer.parseInt(fnt); tea.setFont(new Font("宋体", Font.PLAIN, fs)); System.out.println("字体修改成功!"); diaf.dispose(); } else if ("修改编码类型".equals(commamd)) { encod.setSize(230, 120); fnts1.setFont(new Font("微软雅黑", Font.BOLD, 15)); jwarn.setFont(new Font("微软雅黑", Font.PLAIN, 15)); encod.add(jwarn, BorderLayout.NORTH); encod.add(fnts1, BorderLayout.CENTER); encod.add(conf1, BorderLayout.SOUTH); encod.setLocationRelativeTo(null); encod.setVisible(true); encod.setResizable(false); encod.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); } else if ("确定修改".equals(commamd)) { // 编码修改 String new_enconing = ((String) fnts1.getText()); if (new_enconing.compareTo("UTF-8") == 0 || new_enconing.compareTo("ANSI") == 0) { encoding = fnts1.getText(); System.out.println(encoding); encod.dispose(); System.out.println("成功修改编码至" + fnts1.getText()); } else { JOptionPane.showMessageDialog(encod, "输入编码类型有误(区分大小写)或不支持该编码", "提示", 0); } } else if ("UTF-8".equals(commamd)) { encoding = "UTF-8"; try { res = read("UTF-8"); } catch (IOException e1) { e1.printStackTrace(); } sumT.dispose(); flag = false; value = res; tea.setText(res); txt = tea.getText(); } else if ("ANSI".equals(commamd)) { encoding = "ANSI"; res = read(); sumT.dispose(); flag = false; value = res; tea.setText(res); txt = tea.getText(); } } private void frameSetting() { // 文件菜单 fileMenu.setMnemonic('F');// 设置快捷键ALT+F fileMenu_New = new JMenuItem("新建"); fileMenu_New.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 2)); fileMenu_New.addActionListener(this); fileMenu_Open = new JMenuItem("打开..."); fileMenu_Open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 2)); fileMenu_Open.addActionListener(this); fileMenu_Save = new JMenuItem("保存"); fileMenu_Save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 2)); fileMenu_Save.addActionListener(this); fileMenu_SaveAs = new JMenuItem("另存为..."); fileMenu_SaveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 3)); fileMenu_SaveAs.addActionListener(this); fileMenu_Exit = new JMenuItem("退出"); fileMenu_Exit.addActionListener(this); // 编辑菜单 editMenu.setMnemonic('E');// 设置快捷键ALT+E editMenu_Undo = new JMenuItem("撤销"); editMenu_Undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, 2)); editMenu_Undo.addActionListener(this); editMenu_Redo = new JMenuItem("重做"); editMenu_Redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, 2)); editMenu_Redo.addActionListener(this); editMenu_Cut = new JMenuItem("剪切"); editMenu_Cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, 2)); editMenu_Cut.addActionListener(this); editMenu_Copy = new JMenuItem("复制"); editMenu_Copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 2)); editMenu_Copy.addActionListener(this); editMenu_Paste = new JMenuItem("粘贴"); editMenu_Paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, 2)); editMenu_Paste.addActionListener(this); editMenu_Delete = new JMenuItem("删除"); editMenu_Delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); editMenu_Delete.addActionListener(this); editMenu_All = new JMenuItem("全选"); editMenu_All.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 2)); editMenu_All.addActionListener(this); editMenu_Find = new JMenuItem("查找"); editMenu_Find.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, 2)); editMenu_Find.addActionListener(this); editMenu_Replace = new JMenuItem("替换..."); editMenu_Replace.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, 2)); editMenu_Replace.addActionListener(this); editMenu_Coding = new JMenuItem("修改编码类型"); editMenu_Coding.addActionListener(this); // 查看菜单 viewMenu.setMnemonic('V');// 设置快捷键ALT+V viewMenu_Statistics = new JMenuItem("字数统计"); viewMenu_Statistics.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_J, 2)); viewMenu_Statistics.addActionListener(this); viewMenu_Style = new JMenuItem("字体大小"); viewMenu_Style.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, 2)); viewMenu_Style.addActionListener(this); // 帮助菜单 helpMenu.setMnemonic('H');// 设置快捷键ALT+H helpMenu_About = new JMenuItem("关于"); helpMenu_About.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 3)); helpMenu_About.addActionListener(this); // 添加到菜单 fileMenu.add(fileMenu_New); fileMenu.addSeparator(); fileMenu.add(fileMenu_Open); fileMenu.add(fileMenu_Save); fileMenu.add(fileMenu_SaveAs); fileMenu.addSeparator(); fileMenu.add(fileMenu_Exit); editMenu.add(editMenu_Undo); editMenu.add(editMenu_Redo); editMenu.addSeparator(); editMenu.add(editMenu_Cut); editMenu.add(editMenu_Copy); editMenu.add(editMenu_Paste); editMenu.add(editMenu_Delete); editMenu.add(editMenu_All); editMenu.addSeparator(); editMenu.add(editMenu_Find); editMenu.add(editMenu_Replace); editMenu.add(editMenu_Coding); viewMenu.add(viewMenu_Statistics); viewMenu.add(viewMenu_Style); helpMenu.add(helpMenu_About); // 创建右键弹出菜单 popupMenu = new JPopupMenu(); popupMenu_Undo = new JMenuItem("撤销"); popupMenu_Undo.addActionListener(this); popupMenu_Redo = new JMenuItem("重做"); popupMenu_Redo.addActionListener(this); popupMenu_Cut = new JMenuItem("剪切"); popupMenu_Cut.addActionListener(this); popupMenu_Copy = new JMenuItem("复制"); popupMenu_Copy.addActionListener(this); popupMenu_Paste = new JMenuItem("粘贴"); popupMenu_Paste.addActionListener(this); popupMenu_Delete = new JMenuItem("删除"); popupMenu_Delete.addActionListener(this); popupMenu_All = new JMenuItem("全选"); popupMenu_All.addActionListener(this); // 向右键菜单添加菜单项和分隔符 popupMenu.add(popupMenu_Undo); popupMenu.add(popupMenu_Redo); popupMenu.addSeparator(); popupMenu.add(popupMenu_Cut); popupMenu.add(popupMenu_Copy); popupMenu.add(popupMenu_Paste); popupMenu.add(popupMenu_Delete); popupMenu.addSeparator(); popupMenu.add(popupMenu_All); } // 读取命令 public String read() { // ANSI读取 String temp = ""; try { FileInputStream fis = new FileInputStream(f.getAbsolutePath()); byte[] b = new byte[1024]; while (true) { int num = fis.read(b); if (num == -1) break; temp = temp + new String(b, 0, num); } fis.close(); } catch (Exception e1) { e1.printStackTrace(); } return temp; } @SuppressWarnings("resource") public String read(String encoding) throws IOException { // UTF-8读取 File file = new File(f.getAbsolutePath()); String message = "";// 获取文件内容 if (file.isFile() && file.exists()) { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding)); String buff; while ((buff = br.readLine()) != null) { message = message + buff + "\n"; } } return message; } public void write() { if (f.exists()) { int i = JOptionPane.showConfirmDialog(null, "此位置已出现重名文件,是否保存该文件并删除之前文件", "确认保存", JOptionPane.YES_NO_OPTION); if (i == JOptionPane.OK_OPTION) { try { if (encoding.equals("UTF-8")) { BufferedWriter fos = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(f), encoding)); System.out.println("已成功删除已有文件并保持当前文件"); fos.write(tea.getText()); System.out.println("22222"); fos.close(); } else { Writer fos = new OutputStreamWriter(new FileOutputStream(f, false), "GB2312"); System.out.println("已成功删除已有文件并保持当前文件"); fos.write(tea.getText()); fos.close(); } } catch (Exception e) { e.printStackTrace(); } } } else try { if (encoding.equals("UTF-8")) { BufferedWriter fos = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), encoding)); System.out.println("已成功删除已有文件并保持当前文件"); fos.write(tea.getText()); System.out.println("22222"); fos.close(); } else { Writer fos = new OutputStreamWriter(new FileOutputStream(f, false), "GB2312"); System.out.println("已成功删除已有文件并保持当前文件"); fos.write(tea.getText()); fos.close(); } } catch (Exception e) { e.printStackTrace(); } } // 新建命令 public void NewFile() { frame.dispose(); Notepad note = new Notepad(); // 关闭的时候询问是否保存文件 note.frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { note.Exit(); } }); } public void Exit() { String tst = new String(tea.getText()); if (!flag) { // 如果有源文件 if (txt.equals(tst)) { // 判断文本是否有改动 System.exit(0); } else { // 有改动 int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存", JOptionPane.YES_NO_CANCEL_OPTION); if (i == JOptionPane.OK_OPTION) { write(); } else if (i == JOptionPane.NO_OPTION) { System.exit(0); } } } else { // 无源文件 if (txt.equals(tst)) { // 判断文本是否有改动 System.exit(0); } else { // 有改动 int i = JOptionPane.showConfirmDialog(null, "是否保存您所做的更改?点击“否”将直接退出不做更改!", "确认保存", JOptionPane.YES_NO_CANCEL_OPTION); if (i == JOptionPane.OK_OPTION) { SaveF rep = new SaveF(); // 调用保存类 f = rep.f; write(); } else if (i == JOptionPane.NO_OPTION) { System.exit(0); } } } } public static void main(String[] args) { // 生成Windows风格的UI界面 try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { e.printStackTrace(); } ; Notepad note = new Notepad(); note.frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { note.Exit(); } }); } } class T1 extends FileFilter { // 继承文件对话框的并添加文件筛选后缀名 String ends; // 文件后缀 String description; // 文件描述文字 public T1(String ends, String description) { // 构造函数 this.ends = ends; // 设置文件后缀 this.description = description; // 设置文件描述文字 } @Override // 只显示符合扩展名的文件,目录全部显示 public boolean accept(File file) { if (file.isDirectory()) return true; String fileName = file.getName(); if (fileName.toUpperCase().endsWith(this.ends.toUpperCase())) return true; return false; } @Override // 返回这个扩展名过滤器的描述 public String getDescription() { if (this.description == "所有文件") this.description = "文件"; return this.description; } // 返回这个扩展名过滤器的扩展名 public String getEnds() { return this.ends; } } class SaveF { // 保存文件类 File f; JFileChooser rep = new JFileChooser("%homepath%"); T1 txtFilter = new T1(".txt", "文件文档 (*.txt)"); T1 txtFilter1 = new T1(".ini", "配置文件 (*.ini)"); SaveF() { rep.addChoosableFileFilter(txtFilter); rep.addChoosableFileFilter(txtFilter1); int returnVal = rep.showDialog(null, "保存"); if (returnVal == JFileChooser.APPROVE_OPTION) { // 在文件选择后再执行保存命令 if (!(rep.getFileFilter().getDescription() == "所有文件")) { File file = rep.getSelectedFile(); // 获得文件名 // 获得被选中的过滤器 T1 filter = (T1) rep.getFileFilter(); // 获得过滤器的扩展名 String ends = filter.getEnds(); File newFile = null; if (file.getAbsolutePath().toUpperCase().endsWith(ends.toUpperCase())) { // 如果文件是以选定扩展名结束的,则使用原名 newFile = file; System.out.println("保存路径:" + newFile.getAbsolutePath()); f = new File(newFile.getAbsolutePath()); } else { // 否则加上选定的扩展名 newFile = new File(file.getAbsolutePath() + ends); System.out.println("保存路径:" + newFile.getAbsolutePath()); f = new File(newFile.getAbsolutePath()); } } else { f = rep.getSelectedFile(); System.out.println("保存路径:" + f); } } } } .getName(); if (fileName.toUpperCase().endsWith(this.ends.toUpperCase())) return true; return false; } @Override // 返回这个扩展名过滤器的描述 public String getDescription() { if (this.description == "所有文件") this.description = "文件"; return this.description; } // 返回这个扩展名过滤器的扩展名 public String getEnds() { return this.ends; } } class SaveF { // 保存文件类 File f; JFileChooser rep = new JFileChooser("%homepath%"); T1 txtFilter = new T1(".txt", "文件文档 (*.txt)"); T1 txtFilter1 = new T1(".ini", "配置文件 (*.ini)"); SaveF() { rep.addChoosableFileFilter(txtFilter); rep.addChoosableFileFilter(txtFilter1); int returnVal = rep.showDialog(null, "保存"); if (returnVal == JFileChooser.APPROVE_OPTION) { // 在文件选择后再执行保存命令 if (!(rep.getFileFilter().getDescription() == "所有文件")) { File file = rep.getSelectedFile(); // 获得文件名 // 获得被选中的过滤器 T1 filter = (T1) rep.getFileFilter(); // 获得过滤器的扩展名 String ends = filter.getEnds(); File newFile = null; if (file.getAbsolutePath().toUpperCase().endsWith(ends.toUpperCase())) { // 如果文件是以选定扩展名结束的,则使用原名 newFile = file; System.out.println("保存路径:" + newFile.getAbsolutePath()); f = new File(newFile.getAbsolutePath()); } else { // 否则加上选定的扩展名 newFile = new File(file.getAbsolutePath() + ends); System.out.println("保存路径:" + newFile.getAbsolutePath()); f = new File(newFile.getAbsolutePath()); } } else { f = rep.getSelectedFile(); System.out.println("保存路径:" + f); } } } }

你可能感兴趣的:(java,swing,eclipse,gui,windows)