基于javax.swing的 Java 仿windows记事本
此代码为笔者大二实验课耗时一天所编写,不足之处欢迎大家指正与讨论。笔者对于java了解与使用程度有限,还请多包含。
转载使用请标明原文出处!
https://blog.csdn.net/weixin_43991786/article/details/85251991
所实现的功能
几乎可以说是复刻了windows记事本的所有功能
存在的bug
- 新建文件仍存在bug(新建之后原有文件若是不保存,则清空原有文件字段)
- 状态栏仅实现了显示功能
- 状态栏与自动换行功能使用后无法关闭(只能靠重启程序或者新建文本)
代码
import java.awt.*;
import javax.swing.* ;
import java.awt.event.* ;
import java.io.*;
import javax.swing.undo.UndoManager;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.border.EtchedBorder;
public class Note extends JFrame implements ActionListener{
JMenuBar mb = new JMenuBar(); //创建菜单栏
JMenu file = new JMenu("文件(F)"); //第一层菜单栏
JMenu edit = new JMenu("编辑(E)");
JMenu format = new JMenu("格式(O)");
JMenu view = new JMenu("查看(V)");
JMenu help = new JMenu("帮助(H)");
//文件
JMenuItem
newFile = new JMenuItem("新建(N)"),
open = new JMenuItem("打开(O)"),
save = new JMenuItem("保存(S)"),
save_as = new JMenuItem("另存为(A)"),
exit = new JMenuItem("退出(X)");
//编辑
JMenuItem
undo = new JMenuItem("撤销(U)"),
cut = new JMenuItem("剪切(T)"),
copy = new JMenuItem("复制(C)"),
paste = new JMenuItem("粘贴(P)"),
delete = new JMenuItem("删除(L)"),
find = new JMenuItem("查找(D)"),
Goto = new JMenuItem("转到(G)"),
select_all = new JMenuItem("全选(A)"),
time = new JMenuItem("时间/日期(D)") ; //复选框
//格式
JMenuItem
autoLineWrap = new JMenuItem("自动换行(W)"),
font = new JMenuItem("字体(F)");
//查看
JMenuItem
status = new JMenuItem("状态栏(S)");
//帮助
JMenuItem
about_us = new JMenuItem("关于记事本(A)");
//右键菜单
JMenuItem
cut_2 = new JMenuItem("剪切(T)"),
copy_2 = new JMenuItem("复制(C)"),
paste_2 = new JMenuItem("粘贴(P)"),
select_all_2 = new JMenuItem("全选(A)");
//文本域
private JTextArea txt = new JTextArea();
UndoManager um = new UndoManager();
//弹出菜单
private JPopupMenu jpm = new JPopupMenu() ;
//超行可滚动
JScrollPane scroll = new JScrollPane(txt, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
String pathSelect; //路径
String name = "无标题 – 记事本"; //文件名
JLabel statusLabel;
JLabel statusLabel2;
//name = shlNotepad.setText((new File( fileDir.trim())).getName());
//获取屏幕的尺寸
private int x = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
private int y = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
public Note() {
//设置键盘快捷键
file.setMnemonic(KeyEvent.VK_F);
edit.setMnemonic(KeyEvent.VK_E);
format.setMnemonic(KeyEvent.VK_O);
help.setMnemonic(KeyEvent.VK_H);
view.setMnemonic(KeyEvent.VK_V);
about_us.setMnemonic(KeyEvent.VK_A);
status.setMnemonic(KeyEvent.VK_S);
autoLineWrap.setMnemonic(KeyEvent.VK_W);
font.setMnemonic(KeyEvent.VK_F);
exit.setMnemonic(KeyEvent.VK_X);
save_as.setMnemonic(KeyEvent.VK_A);
newFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK));
copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK));
find.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, ActionEvent.CTRL_MASK));
select_all.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.CTRL_MASK));
time.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5,0));
//设置事件的监听者
save.addActionListener(this);
newFile.addActionListener(this);
open.addActionListener(this);
save_as.addActionListener(this);
exit.addActionListener(this);
undo.addActionListener(this);
cut.addActionListener(this);
cut_2.addActionListener(this);
copy.addActionListener(this);
copy_2.addActionListener(this);
paste.addActionListener(this);
paste_2.addActionListener(this);
delete.addActionListener(this);
find.addActionListener(this);
Goto.addActionListener(this);
select_all.addActionListener(this);
select_all_2.addActionListener(this);
time.addActionListener(this);
autoLineWrap.addActionListener(this);
font.addActionListener(this);
status.addActionListener(this);
about_us.addActionListener(this);
// 设置撤销文本的管理器
txt.getDocument().addUndoableEditListener(um);
txt.setFont(Format.font);
//文件
file.add(newFile);
file.add(open);
file.add(save);
file.add(save_as);
file.addSeparator();
file.add(exit);
//编辑
edit.add(undo);
edit.addSeparator();
edit.add(cut);
edit.add(copy);
edit.add(paste);
edit.add(delete);
edit.addSeparator();
edit.add(find);
edit.add(Goto);
edit.addSeparator();
edit.add(select_all);
edit.add(time);
//格式
format.add(autoLineWrap);
format.add(font);
//查看
view.add(status);
//帮助
help.add(about_us);
//菜单栏
mb.add(file);
mb.add(edit);
mb.add(format);
mb.add(view);
mb.add(help);
//右键菜单
jpm.add(cut_2);
jpm.add(copy_2);
jpm.add(paste_2);
jpm.addSeparator(); //为粘贴到全选之间加根横线
jpm.add(select_all_2);
//添加右键菜单到文本容器
txt.add(jpm);
//鼠标右键动作监听器
txt.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON3) {
jpm.show(txt, e.getX(), e.getY());
}
}
});
//边界布局
this.add(mb, BorderLayout.NORTH);
this.add(scroll, BorderLayout.CENTER);
this.setSize(600, 850);
this.setTitle(name);
this.setLocationRelativeTo(null); //设置窗口相对于指定组件的位置为 null,则此窗口将置于屏幕的中央
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//设置按"X"按钮时候的动作,一般都会把它设成退出程序,相当于是System.exit(0);的动作
this.setVisible(true);
}
// 重写actionPerformed
public void actionPerformed(ActionEvent e) {
//对象发生源
//打开
if (e.getSource() == open) { //getSource()返回最初发生的对象
open();
}
//另存为
if(e.getSource() == save_as)
save_as();
if(e.getSource() == save && (pathSelect == null))
save_1();
else if (e.getSource() == save && !(pathSelect == null))
save_2();
if (e.getSource() == newFile) {
newFile();
}
if(e.getSource() == exit) {
System.exit(0);
}
if(e.getSource() == undo) {
if (um.canUndo()) { //canUndo()用于判断undo操作是否成功,如果成功就返回true。
um.undo(); //撤销操作
}
}
if(e.getSource() == time) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置日期格式
//df.format(new Date()) //new Date()为所获取的系统时间
txt.setText(df.format(new Date()));
}
if(e.getSource() == autoLineWrap) {
txt.setWrapStyleWord(true);
txt.setLineWrap(true);
}
if(e.getSource() == status) {
JPanel panel1=new JPanel();
statusLabel=new JLabel("");
statusLabel2=new JLabel("文件状态");
panel1.add(statusLabel);
panel1.add(statusLabel2);
this.add(panel1,BorderLayout.SOUTH);
this.setVisible(true);
}
if(e.getSource() == delete)
txt.replaceSelection(""); //删除
//直接调用JTextArea()中的cut();copy();paste()
if (e.getSource() == cut || e.getSource() == cut_2)
txt.cut();
else if(e.getSource() == copy || e.getSource() == copy_2)
txt.copy();
else if (e.getSource() == paste || e.getSource() == paste_2)
txt.paste();
else if(e.getSource() == find)
new fandr(txt);
else if (e.getSource() == select_all || e.getSource() == select_all_2)
txt.selectAll();
if (e.getSource() == font)
new Format(txt);
if (e.getSource() == about_us)
JOptionPane.showMessageDialog(null, "记事本\nVersion 1.0\nJRE Version 8.0\n作者:hongcaisen", "关于",JOptionPane.PLAIN_MESSAGE);
}
Note(String title){
this.setTitle(title);
}
void open() {
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("文本文档(*.txt)", "txt");
chooser.setFileFilter(filter); //过滤非.txt后缀的文件,详情见笔记
chooser.setDialogTitle("文件打开"); //标题
chooser.showOpenDialog(null); //弹出文件位置为中间
chooser.setVisible(true);
name = chooser.getSelectedFile().getName();
this.setTitle(name);
try {
pathSelect = chooser.getSelectedFile().getPath(); //返回定义时的路径
FileReader reader = new FileReader(pathSelect);
BufferedReader buffer = new BufferedReader(reader);
//文本读入与缓冲区读入
String temp = "", temp_1 = "";
while ((temp = buffer.readLine()) != null) { //readLine()读取一个文本行
temp_1 += (temp + "\n");
txt.setText(temp_1); //逐行读取文本
}
}catch(Exception e1) {}
}
void save_1() { //保存
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("保存");
chooser.showSaveDialog(null);
chooser.setVisible(true);
name = chooser.getSelectedFile().getName();
this.setTitle(name);
PrintStream ps;
try {
pathSelect = chooser.getSelectedFile().getPath();
ps = new PrintStream(pathSelect);
System.setOut(ps);
System.out.println(this.txt.getText());
} catch (Exception e1) {}
}
void save_2() {
PrintStream ps;
try {
ps = new PrintStream(pathSelect);
System.setOut(ps);
System.out.println(this.txt.getText());
} catch (FileNotFoundException e1) {}
}
void save_as() { //与打开类似
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("文本文档(*.txt)", "txt");
chooser.setFileFilter(filter);
chooser.setDialogTitle("另存为");
chooser.showSaveDialog(null);
chooser.setVisible(true);
name = chooser.getSelectedFile().getName();
this.setTitle(name);
PrintStream ps;
try {
String select = chooser.getSelectedFile().getPath();
ps = new PrintStream(select);
System.setOut(ps);
System.out.println(this.txt.getText());
} catch (Exception e1) {}
}
void newFile() {
txt.setText("");
pathSelect = null;
int n = JOptionPane.showConfirmDialog(null, "你还未保存文件\n是否进行保存操作", "警告",JOptionPane.YES_NO_OPTION); //返回值为0或1
if(n == 1) //不保存
{
new Note();
}
else if(n == 0) //保存
{
save_as();
new Note();
}
}
public static void main(String[] args) {
new Note();
}
}
class fandr extends JDialog implements ActionListener { //替换
JLabel findLabel = new JLabel("查找内容(N):");
JLabel repLabel = new JLabel ("替换为(F): ");
JTextField text_1 = new JTextField(8);
JTextField text_2 = new JTextField(8);
JButton fb = new JButton("查找下一处(F)");
JButton rb = new JButton(" 替换(R): ");
JPanel fp = new JPanel();
JPanel rp = new JPanel();
JTextArea txt;
String text;
boolean flg = false;
int len;
int start = 0;
int k = 0;
public fandr(JTextArea txt) {
this.txt = txt;
fp.add(findLabel);
fp.add(text_1);
fp.add(fb);
rp.add(repLabel);
rp.add(text_2);
rp.add(rb);
this.add(fp);
this.add(rp);
fb.addActionListener(this);
rb.addActionListener(this);
this.setTitle("查找和替换");
this.setLayout(new GridLayout(2, 1));
// this.setBounds(400, 200, 300, 140);
this.pack();
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);//详情看上一个这个函数的用法(或笔记)
}
public void actionPerformed(ActionEvent e) {
String findText = text_1.getText();
String repText = text_2.getText();
text = txt.getText();
if (e.getSource() == fb) {
fb.setLabel("查找下一处(F)");
if (findText != null) {
len = findText.length();
start = text.indexOf(findText, k);
k = start + len;
txt.select(start, start + len);
flg = true;
if (start == -1) {
JOptionPane.showMessageDialog(null, "已到文件尾部!", "提示", JOptionPane.INFORMATION_MESSAGE);
start = 0;
k = 0;
flg = false;
}
}
} else if (e.getSource() == rb) {
if (flg) {
txt.replaceRange(repText, start, start + len);
flg = false;
}
}
}
}
class Format extends JDialog implements ActionListener {
public static int style = 0; // 全局变量类型,默认值为0
public static int size = 16; // 全局变量字体大小,默认值为16
public static Font font = new Font("新宋体", style, size); // 全局变量字体,默认值为新宋体
JPanel pn = new JPanel();
JPanel okCelPn = new JPanel();
JPanel fp = new JPanel();
JPanel ptPn = new JPanel();
JLabel fontLabel = new JLabel("字体: ");
JLabel fontStyleLabel = new JLabel(" 字形: ");
JLabel ptLabel = new JLabel(" 磅值: ");
JButton ok = new JButton("确定");
JButton cancel = new JButton("取消");
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();// 获取系统中可用的字体的名字
String[] fontName = e.getAvailableFontFamilyNames();// 获取系统中可用的字体的名字
String[] fontType = { "常规", "倾斜", "粗体", "粗偏斜体" };
JList fontList = new JList(fontName);
JList fontTypeList = new JList(fontType);
JScrollPane fontScroll = new JScrollPane(fontList);
JScrollPane fontTypeScroll = new JScrollPane(fontTypeList);
JTextArea textarea;
SpinnerModel spinnerModel = new SpinnerNumberModel(size, // initial value
0, // min
100, // max
2 // Step
);
JSpinner spinner = new JSpinner(spinnerModel);
public Format(JTextArea textarea) {
this.textarea = textarea;
ok.addActionListener(this);
cancel.addActionListener(this);
pn.setLayout(new GridLayout(2, 1));
pn.add(fp);
pn.add(ptPn);
fp.add(fontLabel);
fp.add(fontScroll);
fp.add(fontStyleLabel);
fp.add(fontTypeScroll);
ptPn.add(ptLabel);
ptPn.add(spinner);
fontList.setVisibleRowCount(5);
fontList.setFixedCellWidth(60);
fontList.setSelectedIndex(50);
fontList.setSelectedValue(font.getFontName(), true);
fontTypeList.setVisibleRowCount(5);
fontTypeList.setSelectedIndex(style);
okCelPn.add(ok);
okCelPn.add(cancel);
okCelPn.setLayout(new FlowLayout(FlowLayout.RIGHT));
this.add(pn, BorderLayout.CENTER);
this.add(okCelPn, BorderLayout.SOUTH);
this.setTitle("字体");
this.pack();
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == ok) {
System.out.println(fontList.getSelectedValue());
style = this.type();
size = Integer.parseInt(spinner.getValue().toString());
font = new Font((String) fontList.getSelectedValue(), style, size);
textarea.setFont(font);
this.dispose();
System.out.println(type());
} else if (e.getSource() == cancel) {
this.dispose();
}
}
private int type() {
if (fontTypeList.getSelectedValue().equals("倾斜")) {
return 1;
} else if (fontTypeList.getSelectedValue().equals("粗体")) {
return 2;
} else if (fontTypeList.getSelectedValue().equals("粗偏斜体")) {
return 3;
} else
return 0;
}
}