分享刚完成的模拟记事本的java源代码

因为大部分的内容都是摘自林老师的JDK7学习笔记的,只做了细微的修改,所以就定为转载了。

=============================JNotePad.java=============================

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.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

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 JNotePad extends JFrame {

	private TextDAO textDAO;
	/**
	 * 按照Eclipse的提示,给这个可以序列化的JNotePad加上serialVersionUID 虽然书上没有这个内容。
	 */
	private static final long serialVersionUID = 1L;
	// 为各个menu相关对象命名,再回忆一下关系 Bar - Menu - Item
	private JMenuBar menuBar;
	// 首先,上面是菜单栏
	private JMenu fileMenu;
	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 JMenu aboutMenu;
	private JMenuItem menuAbout;

	// 文字编辑区和状态栏
	private JTextArea textArea;
	private JLabel stateBar;

	// 文本区域的右击弹出窗口
	private JPopupMenu popUpMenu;

	// 用来选择文件的fileChooser
	private JFileChooser fileChooser;

	// 由于P442,需要将如何具体地创建、读、保存文本文件的方法传入构造器,于是创建一个新的构造器
	public JNotePad(TextDAO textDAO) {
		this();
		this.textDAO = textDAO;
	}

	// 这里就是构造器了,P429提到说,在这里就需要对JFrame中的组件进行组合
	// 由于P442修改了构造器,对公的构造器只有传入具体操作接口的上面那个构造器,这个构造器改为protected的。原因我目前还不知道。
	protected JNotePad() {
		initComponents();
		initEventListeners();
	}

	// 初始化组件,对JNotePad设置标题,并设置尺寸。
	// 初始化组件的时候,要把组件都加上去。
	private void initComponents() {
		this.setTitle("新增纯文本文档");
		this.setSize(400, 300);
		// 新建第一个菜单
		fileMenu = new JMenu("文档");
		menuOpen = new JMenuItem("打开文档");
		menuSave = new JMenuItem("保存文档");
		menuSaveAs = new JMenuItem("另存为");
		menuClose = new JMenuItem("关闭");
		// 然后对菜单进行组装。
		fileMenu.add(menuOpen);
		fileMenu.addSeparator();
		fileMenu.add(menuSave);
		fileMenu.addSeparator();
		fileMenu.add(menuSaveAs);
		fileMenu.addSeparator();
		fileMenu.add(menuClose);

		// 新建第二个菜单
		editMenu = new JMenu("编辑");
		menuCut = new JMenuItem("剪切");
		menuCopy = new JMenuItem("复制");
		menuPaste = new JMenuItem("黏贴");
		// 组装
		editMenu.add(menuCut);
		editMenu.add(menuCopy);
		editMenu.add(menuPaste);

		// 第三个菜单
		aboutMenu = new JMenu("关于");
		menuAbout = new JMenuItem("关于JNotePad");
		aboutMenu.add(menuAbout);

		// 菜单栏增加各个菜单
		menuBar = new JMenuBar();
		menuBar.add(fileMenu);
		menuBar.add(editMenu);
		menuBar.add(aboutMenu);

		// 把menuBar加到JFrame上
		this.setJMenuBar(menuBar);
		// 在这里对文本编辑区和状态栏做初始化操作
		textArea = new JTextArea();
		// 设置字体
		textArea.setFont(new Font("宋体", Font.PLAIN, 16));
		// 自动换行
		textArea.setLineWrap(true);
		// 给出JScrollPane,并往JScrollPane中,增加文本编辑区
		// 已经设置了自动换行,则水平滚动条已不需要,设置垂直滚动条为asNeeded。
		JScrollPane panel = new JScrollPane(textArea,
				ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
				ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		// MenuBar和ContentPane在窗口中,共同分享大小。除开menuBar的地盘,剩下的就都是ContentPane的了。
		// 之所以这边使用的是Container类呢,是因为JFrame的getContentPane()方法本身返回的类型就是Container。
		Container contentPane = this.getContentPane();
		// textArea -> panel -> contentPane
		// BorderLayout.CENTER用来设置contentPane的东西南北中,五个区域里的中。
		contentPane.add(panel, BorderLayout.CENTER);
		// 然后再给contentPane加上stateBar
		stateBar = new JLabel("未修改");
		// 设置JLabel中的文字水平左边对齐
		stateBar.setHorizontalAlignment(SwingConstants.LEFT);
		// 设置JLabel的边框为蚀刻边框
		stateBar.setBorder(BorderFactory.createEtchedBorder());
		// 接下去就可以加进去了
		contentPane.add(stateBar, BorderLayout.SOUTH);
		// 创建文本区域的右击弹出窗口
		popUpMenu = editMenu.getPopupMenu();
		// 创建JFileChooser并赋给fileChooser
		fileChooser = new JFileChooser();
	}

	// 初始化事件监听器
	private void initEventListeners() {
		// 监听的是,关闭按钮事件
		// 已经通过WindowsAdapter重写windowClosing方法,所以这句就不需要了。
		// this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// 监听快捷键,对应一个MenuItem设置一个对应的快捷键。这样按下一个快捷键,就等同于单击了那个menuItem
		menuOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
				InputEvent.CTRL_MASK));
		menuSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
				InputEvent.CTRL_MASK));
		menuClose.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
				InputEvent.CTRL_MASK));
		menuCut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
				InputEvent.CTRL_MASK));
		menuCopy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
				InputEvent.CTRL_MASK));
		menuPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,
				InputEvent.CTRL_MASK));
		// 增加窗口关闭按钮的监听器,而不再使用默认的关闭动作
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				closeFile();
			}
		});
		// 打开菜单项目监听器
		menuOpen.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				openFile();
			}
		});
		// 存储菜单项目监听器
		menuSave.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				saveFile();
			}
		});
		// 另存为菜单项目监听器
		menuSaveAs.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				saveFileAs();
			}
		});
		// 关闭菜单项目监听器
		menuClose.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				closeFile();
			}
		});
		// 剪切菜单项目监听器
		menuCut.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				cut();
			}
		});
		// 复制菜单项目监听器
		menuCopy.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				copy();
			}
		});
		// 黏贴菜单项目监听器
		menuPaste.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				paste();
			}
		});
		// 关于菜单项目监听器
		menuAbout.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				JOptionPane.showOptionDialog(null,
						"JNotePad 0.1\n 来自 krave@163.com", "关于JNotePad",
						JOptionPane.YES_NO_OPTION,
						JOptionPane.INFORMATION_MESSAGE, null, null, null);
			}
		});
		// 文本编辑区按键监听器
		textArea.addKeyListener(new KeyAdapter() {
			public void keyTyped(KeyEvent e) {
				jtextAreaActionPerformed();
			}
		});
		// 文本编辑区鼠标右键弹菜单监听器
		textArea.addMouseListener(new MouseAdapter() {
			public void mouseReleased(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3) {
					popUpMenu.show(textArea, e.getX(), e.getY());
				}
			}

			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON1) {
					popUpMenu.setVisible(false);
				}
			}
		});

	}

	private void closeFile() {
		// 检查文本内容是否变更过
		if (stateBar.getText().equals("未修改")) {
			// 则说明已经存储过文件,或者记事本打开后就没编辑过东西。直接关闭即可。
			this.dispose();
		} else {
			// 如果修改过了,就询问是否要保存,保存的话,调用保存方法,不然就直接关闭了哈。
			int option = JOptionPane.showConfirmDialog(null, "文档修改过了,要保存不?",
					"保存文档?", JOptionPane.YES_NO_OPTION,
					JOptionPane.WARNING_MESSAGE, null);
			switch (option) {
			case JOptionPane.YES_OPTION:
				saveFile();
				dispose();
				break;
			case JOptionPane.NO_OPTION:
				dispose();
			}
		}
	}

	private void openFile() {
		if (stateBar.getText().equals("未修改")) {
			// 如果文本内容为:未修改,则直接调用选取文件的对话框
			showFileDialog(); // 显示文件对话框,打开现已存在的文件
		} 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:
				showFileDialog(); // 显示文件对话框,打开现已存在的文件
				break;
			}
		}
	}

	private void showFileDialog() {
		int option = fileChooser.showDialog(null, null);// 显示文件选择对话框,并且对对话框做出选择
		if (option == JFileChooser.APPROVE_OPTION) {
			try {
				// 设定JNotePad的标题为文件名
				this.setTitle(fileChooser.getSelectedFile().toString());
				// 清空文本框
				textArea.setText("");
				stateBar.setText("未修改");
				// 实际上这一块可以坐优化,因为fileChooser本身就可以返回File对象了。
				String text = textDAO.read(fileChooser.getSelectedFile()
						.toString());
				// 把选择的文本文件的文字内容添加到文本框中
				textArea.setText(text);
			} catch (Exception e) {
				e.printStackTrace();
				JOptionPane.showMessageDialog(null, e.toString(), "打开文档失败",
						JOptionPane.ERROR_MESSAGE);
			}
		}
	}

	private void saveFile() {
		// 先从标题栏取得文件名
		Path path = Paths.get(this.getTitle());
		if (Files.notExists(path)) {
			saveFileAs();
		} else {
			// 如果这个文档存在的话,就直接保存
			try {
				// 调用保存方法
				textDAO.save(path.toString(), textArea.getText());
				// 将状态栏变更为未修改
				stateBar.setText("未修改");

			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, e.toString(), "保存文档失败",
						JOptionPane.ERROR_MESSAGE);
			}
		}
	}

	private void saveFileAs() {
		// 显示文档选择对话框
		int option = fileChooser.showDialog(null, null);
		// 如果确实选取了文档要保存的话
		if (option == JFileChooser.APPROVE_OPTION) {
			// 在标题栏设置文档路径
			setTitle(fileChooser.getSelectedFile().toString());
			// 调用textDAO来创建新文档并保存
			textDAO.create(fileChooser.getSelectedFile().toString());
			saveFile();
		}// 如果取消的话,关闭文档选择器,恢复到之前的状况。
	}

	private void cut() {
		textArea.cut();
		stateBar.setText("已修改");
		popUpMenu.setVisible(false);
	}

	private void copy() {
		textArea.copy();
		stateBar.setText("已修改");
		popUpMenu.setVisible(false);
	}

	private void paste() {
		textArea.paste();
		stateBar.setText("已修改");
		popUpMenu.setVisible(false);
	}

	private void jtextAreaActionPerformed() {
		stateBar.setText("已修改");
	}

	public static void main(String[] args) {
		javax.swing.SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				new JNotePad(new FileTextDAO()).setVisible(true);
			}
		});

	}
}

=============================TextDAO.java=============================

public interface TextDAO {
	void create(String file);
	String read(String file);
	void save(String file, String text);
}


=============================FileTextDAO.java=============================

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;

public class FileTextDAO implements TextDAO {
	@Override
	public void create(String file) {
		try {
			Files.createFile(Paths.get(file));
		} catch (Exception e) {
			Logger.getLogger(FileTextDAO.class.getName()).log(Level.SEVERE,
					null, e);
		}
	}

	@Override
	public void save(String file, String text) {
		try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(file),
				Charset.forName(System.getProperty("file.encoding")))) {
			writer.write(text);
		} catch (IOException e) {
			Logger.getLogger(FileTextDAO.class.getName()).log(Level.SEVERE,
					null, e);
		}
	}

	@Override
	public String read(String file) {
		byte[] textData = null;
		try {
			textData = Files.readAllBytes(Paths.get(file));

		} catch (IOException e) {
			Logger.getLogger(FileTextDAO.class.getName()).log(Level.SEVERE,
					null, e);
		}
		return new String(textData);
	}

}



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值