学Java大概也有那么一段时间了,写了些小项目来练手
也算是对之前学的Java基本操作的巩固
照着Windows的记事本用Java Swing实现了一下
欢迎各位大佬批评指正不足之处
首先是主窗口程序:
package com.app.notepadplus;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
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.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.UndoManager;
public class Notepad extends JFrame {
/**
* 初始化方法
*/
private static final long serialVersionUID = 1L;
private static JPopupMenu menu;
private String fileName = "无标题";
private String title = " - 记事本";
private JTextArea area;
private JLabel lblStatus;
private ArrayList mainMenuList;
private Map sonMenuMap;
private Map rightMenuMap;
private JPanel panBottom;
private boolean isOpenFile = false;
private boolean isSaved = true;
private boolean isLineWrap = true;
private File fileOpen;
private JFileChooser jfc;
private Font fontEnd;
private UndoManager um;
private JCheckBoxMenuItem jcb;
private JCheckBoxMenuItem jcbLine;
protected FoundDialog foundDialog;
public Notepad() {
int fWidth = 800;
int fHeight = 600;
this.setSize(fWidth, fHeight);
this.centerWindow();
// 设置UI随系统
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
// 读取序列化的字体格式
if (new File("setting/fontEnd.ser").exists()) {
try {
FileInputStream fileIn = new FileInputStream("setting/fontEnd.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
fontEnd = (Font) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("fontEnd.ser not found");
c.printStackTrace();
return;
}
} else {
fontEnd = new Font("微软雅黑", Font.PLAIN, 12);
}
lblStatus = new JLabel("第 1 行, 第 1 列");
lblStatus.setFont(new Font("微软雅黑", Font.PLAIN, 12));
setBottom();
this.setIconImage(new ImageIcon("images/jiShiBen.png").getImage());
this.setMenu();
this.setText(this);
this.addListener(this);
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.setTitle(fileName);
}
public void setBottom() {
panBottom = new JPanel();
panBottom.setLayout(new GridLayout(1, 4));
panBottom.add(new JLabel());
panBottom.add(new JLabel());
panBottom.add(new JLabel());
panBottom.add(new JLabel());
panBottom.add(new JLabel());
panBottom.add(lblStatus);
JLabel timeLabel = new JLabel();
panBottom.add(timeLabel);
SimpleDateFormat dfLabel = new SimpleDateFormat("HH:mm:ss");// 设置日期格式
// 新建线程实现 右下角时间的显示
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
timeLabel.setText(dfLabel.format(new Date()));
try {
Thread.sleep(1000);// 每秒刷新一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
panBottom.setBorder(new LineBorder(Color.GRAY));
this.add(panBottom, BorderLayout.SOUTH);
}
@Override
public void setTitle(String fileName) {
super.setTitle(fileName + this.title + " ");
}
public void setTitleSuper(String fileName) {
super.setTitle(fileName);
}
private void setMenu() {
// 二维数组保存菜单列表
String[] mainMenu = { "文件(F)", "编辑(E)", "格式(O)", "查看(V)", "帮助(H)" };
String sonMenu[][] = { { "新建(N)", "打开(O)...", "保存(S)", "另存为(A)...", "页面设置(U)...", "打印(P)...", "退出(X)" },
{ "撤销(U)", "剪切(T)", "复制(C)", "粘贴(P)", "删除(L)", "查找(F)...", "查找下一个(N)", "替换(R)...", "转到(G)...", "全选(A)",
"时间/日期(D)" },
{ " 字体(F)..." }, {}, { "查看帮助(H)", "关于记事本(A)", "计算器(C) ", "日历(D)" } };
int kjj1[] = { KeyEvent.VK_F, KeyEvent.VK_E, KeyEvent.VK_O, KeyEvent.VK_V, KeyEvent.VK_H };
int kjj2[][] = {
{ KeyEvent.VK_N, KeyEvent.VK_O, KeyEvent.VK_S, KeyEvent.VK_A, KeyEvent.VK_U, KeyEvent.VK_P,
KeyEvent.VK_X },
{ KeyEvent.VK_Z, KeyEvent.VK_X, KeyEvent.VK_C, KeyEvent.VK_V, KeyEvent.VK_L, KeyEvent.VK_F,
KeyEvent.VK_N, KeyEvent.VK_R, KeyEvent.VK_G, KeyEvent.VK_A, KeyEvent.VK_D },
{ KeyEvent.VK_F }, {}, { KeyEvent.VK_H, KeyEvent.VK_A, KeyEvent.VK_C, KeyEvent.VK_D } };
String kjj3[] = { "11", "12", "13", "15", "21", "22", "23", "24", "26", "28", "29", "210" };
mainMenuList = new ArrayList<>();
sonMenuMap = new HashMap<>();
rightMenuMap = new HashMap<>();
JMenuBar menuBar = new JMenuBar();
Font f = new Font("微软雅黑", Font.PLAIN, 15);
for (int i = 0; i < mainMenu.length; i++) {
mainMenuList.add(new JMenu(mainMenu[i]));
mainMenuList.get(i).setFont(f);
mainMenuList.get(i).setMnemonic(kjj1[i]);
}
for (int i = 0; i < mainMenuList.size(); i++) {
for (int j = 0; j < sonMenu[i].length; j++) {
sonMenuMap.put(String.valueOf((i + 1)) + String.valueOf((j + 1)),
new JMenuItem(sonMenu[i][j], kjj2[i][j]));
sonMenuMap.get(String.valueOf((i + 1)) + String.valueOf((j + 1))).setFont(f);
if (Arrays.asList(kjj3).contains(String.valueOf((i + 1)) + String.valueOf((j + 1)))) {
sonMenuMap.get(String.valueOf((i + 1)) + String.valueOf((j + 1)))
.setAccelerator(KeyStroke.getKeyStroke(kjj2[i][j], ActionEvent.CTRL_MASK));
}
mainMenuList.get(i).add(sonMenuMap.get(String.valueOf((i + 1)) + String.valueOf((j + 1))));
}
menuBar.add(mainMenuList.get(i));
}
// 添加JCheckBox
jcb = new JCheckBoxMenuItem(" 状态栏(S)");
jcb.setSelected(true);
jcb.setFont(f);
jcb.setFocusPainted(false);
jcb.setMnemonic(KeyEvent.VK_S);
mainMenuList.get(3).add(jcb);
jcbLine = new JCheckBoxMenuItem(" 自动换行(W)");
jcbLine.setSelected(true);
jcbLine.setFont(f);
jcbLine.setFocusPainted(false);
jcbLine.setMnemonic(KeyEvent.VK_W);
mainMenuList.get(2).add(jcbLine);
sonMenuMap.get("25").setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
sonMenuMap.get("27").setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0));
sonMenuMap.get("211").setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0));
// 初始化,无内容不可用
sonMenuMap.get("21").setEnabled(false);
sonMenuMap.get("22").setEnabled(false);
sonMenuMap.get("23").setEnabled(false);
sonMenuMap.get("25").setEnabled(false);
sonMenuMap.get("26").setEnabled(false);
sonMenuMap.get("27").setEnabled(false);
// 禁用一些未开发的功能
sonMenuMap.get("15").setEnabled(false);
sonMenuMap.get("16").setEnabled(false);
sonMenuMap.get("51").setEnabled(false);
// 右键子菜单
menu = new JPopupMenu();
for (int j = 0; j < 5; j++) {
rightMenuMap.put(String.valueOf(2) + String.valueOf((j + 1)), new JMenuItem(sonMenu[1][j], kjj2[1][j]));
rightMenuMap.get(String.valueOf(2) + String.valueOf((j + 1))).setFont(f);
menu.add(rightMenuMap.get(String.valueOf(2) + String.valueOf((j + 1))));
}
rightMenuMap.put(String.valueOf(2) + String.valueOf((10)), new JMenuItem(sonMenu[1][9], kjj2[1][9]));
rightMenuMap.get(String.valueOf(2) + String.valueOf((10))).setFont(f);
menu.add(rightMenuMap.get(String.valueOf(2) + String.valueOf((10))));
// 初始化,无内容不可用
rightMenuMap.get("21").setEnabled(false);
rightMenuMap.get("22").setEnabled(false);
rightMenuMap.get("23").setEnabled(false);
rightMenuMap.get("25").setEnabled(false);
this.setJMenuBar(menuBar);
}
private void setText(JFrame app) {
area = new JTextArea();// 构造一个文本域
area.setFont(fontEnd);
area.setLineWrap(isLineWrap);// 如果内容过长,自动换行,在文本域加上滚动条,水平和垂直滚动条始终出现。
JScrollPane pane = new JScrollPane(area);
// 获取当前光标位置信息
area.addCaretListener(new CaretListener() {
public void caretUpdate(CaretEvent e) {
try {
int pos = area.getCaretPosition();
// 获取行数
int lineOfC = area.getLineOfOffset(pos) + 1;
// 获取列数
int col = pos - area.getLineStartOffset(lineOfC - 1) + 1;
lblStatus.setText("第 " + lineOfC + " 行, 第 " + col + " 列");
if (area.getSelectedText() != null) {
if (sonMenuMap.get("22").isEnabled() == false) {
sonMenuMap.get("22").setEnabled(true);
sonMenuMap.get("23").setEnabled(true);
sonMenuMap.get("25").setEnabled(true);
rightMenuMap.get("22").setEnabled(true);
rightMenuMap.get("23").setEnabled(true);
rightMenuMap.get("25").setEnabled(true);
}
} else {
if (sonMenuMap.get("22").isEnabled()) {
sonMenuMap.get("22").setEnabled(false);
sonMenuMap.get("23").setEnabled(false);
sonMenuMap.get("25").setEnabled(false);
rightMenuMap.get("22").setEnabled(false);
rightMenuMap.get("23").setEnabled(false);
rightMenuMap.get("25").setEnabled(false);
}
}
} catch (Exception ex) {
System.out.println("无法获取光标位置");
}
}
});
// 输入监听
um = new UndoManager();
area.getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(UndoableEditEvent e) {
um.addEdit(e.getEdit());
if (sonMenuMap.get("21").isEnabled() == false && um.canUndo()) {
sonMenuMap.get("21").setEnabled(true);
rightMenuMap.get("21").setEnabled(true);
}
isSaved = false;
if (isOpenFile()) {
app.setTitle(fileOpen.getName() + "*");
} else {
app.setTitle(fileName + "*");
}
if (area.getText() != null) {
if (sonMenuMap.get("26").isEnabled() == false) {
sonMenuMap.get("26").setEnabled(true);
sonMenuMap.get("27").setEnabled(true);
}
} else {
if (sonMenuMap.get("26").isEnabled()) {
sonMenuMap.get("26").setEnabled(false);
sonMenuMap.get("27").setEnabled(false);
}
}
}
});
// 右键菜单
area.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
menu.show(area, e.getX(), e.getY());
}
}
});
this.add(pane);
}
protected void centerWindow() {
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
double sWidth = d.getWidth();// 屏幕分辨率的宽
double sHeight = d.getHeight();// 屏幕分辨率的高
double fWidth = this.getWidth();// 窗体的宽
double fHeight = this.getHeight();// 窗体的高
double posX = (sWidth - fWidth) / 2;// 居中位置左上角的x
double posY = (sHeight - fHeight) / 2;// 居中位置左上角的y
this.setLocation((int) posX, (int) posY);
}
public static void setCenterWindow(Component d, int fWidth, int fHeight, JDialog frm) {
double sWidth = d.getWidth();// 屏幕分辨率的宽
double sHeight = d.getHeight();// 屏幕分辨率的高
double posX = (sWidth - fWidth) / 2 + d.getLocation().x;// 居中位置左上角的x
double posY = (sHeight - fHeight) / 2 + d.getLocation().y;// 居中位置左上角的y
frm.setLocation((int) posX, (int) posY);
frm.setResizable(false);
}
/**
* 为菜单添加监听功能
*
* @param app:this
*/
private void addListener(JFrame app) {
app.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (isSaved != true) {
new CloseingDialog((Notepad) app);
} else {
System.exit(0);
}
}
});
// 退出
sonMenuMap.get("17").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (isSaved != true) {
new CloseingDialog((Notepad) app);
} else {
System.exit(0);
}
}
});
// 关于记事本
sonMenuMap.get("52").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new AboutTextDialog((Notepad) app);
}
});
// 计算器
sonMenuMap.get("53").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new CalculatorDialog((Notepad) app);
}
});
// 日历
sonMenuMap.get("54").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new CalendarDialog((Notepad) app, "日历", false);
}
});
// 新建
sonMenuMap.get("11").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (isSaved != true) {
new NewBuildDialog((Notepad) app);
} else {
area.setText(null);
app.setTitle("无标题");
fileOpen = null;
setOpenFile(false);
isSaved = true;
}
}
});
// 字体
sonMenuMap.get("31").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new FontSetDialog((Notepad) app);
}
});
// 查找
sonMenuMap.get("26").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
foundDialog = new FoundDialog((Notepad) app);
}
});
// 查找下一个
sonMenuMap.get("27").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (foundDialog != null && foundDialog.getMsgToFound() != null) {
foundDialog.getBtnNewButton().doClick();
} else {
foundDialog = new FoundDialog((Notepad) app);
}
}
});
// 替换
sonMenuMap.get("28").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new FoundOrReplace((Notepad) app);
}
});
// 另存为
sonMenuMap.get("14").addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String msg = area.getText();
jfc = new JFileChooser("D:/MP3测试歌曲/文本测试文件");
int isChoose = jfc.showSaveDialog(null);
if (jfc.getSelectedFile() != null && isChoose == JFileChooser.APPROVE_OPTION) {
fileOpen = jfc.getSelectedFile();
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(fileOpen));
bw.write(msg);
System.out.println("保存成功!");
bw.close();
app.setTitle(fileOpen.getName());
setOpenFile(true);
isSaved = true;
} catch (IOException e1) {
System.out.println("保存失败!");
setOpenFile(false);
isSaved = false;
}
} else {
System.out.println("no save");
}
}
});
ArrayList
打开程序的话,写个主类调用一下:
package com.app.notepadplus;
public class App {
public static Notepad app;
public static void main(String[] args) {
app = new Notepad();
app.setVisible(true);
}
}
接下来就是各个子窗口,查找,替换,字体设置,计算器之类的辅助功能之类的
太杂了,就不贴了吧。。。。。。
有空把代码打包一下,直接上传吧....