实现一个简易记事本
效果:记事本界面,实现用户编辑内容,文本字体设置,文件保存,文件打开,记事本退出
先来看看最后运行的一个结果界面:(代码在最后)
分析上图,第一个观察简易记事本的主要构成
1.菜单栏
2.文本域
3.给文本域添加的滚动条
第二个考虑窗体布局,明显的使用方位布局–BorderLayout。菜单栏添加到窗体的上方,文本域添加到窗体的中间。
第三个考虑使用到的组件:面板JPanel,菜单栏JMenuBar,菜单JMenu,文本域JTextArea,文本域的滚动条JScrollPane,
还有三个菜单JMenu:file 、edit 、view
第四个,代码的实现思路
1.定义要用到的变量
2.创建主要方法分别实现:变量初始化、组件往窗体上添加、组件事件监听,保存文件,打开文件,记事本退出等功能
代码有一些细节要注意,菜单有哪些都可以自己定义,如下,每俩功能之间都有一条下划线,当然这个不添加也可以。
代码实现
package test2;
//简易记事本,里面的this是调用成员变量,解决局部变量名称冲突问题
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
//继承JFrame的这个父类,实现监听器的接口
public class EasyTXT extends JFrame implements ActionListener {
//观察布局,有菜单栏和文本域两个上下组成,所以用方位布局
//先定义要用到的变量
JPanel jp;//窗体主面板
JTextArea jta;//文本域
JScrollPane jsp;//文本域的滚动条
JMenuBar jmb;//菜单栏组件
JMenu file,edit,view;//菜单内容
File currentFile=null;//当前打开的文件
boolean wasSaved=true;//当前文件是否保存
public void TextEditor(){ //该方法实现对组件的初始化
jp=new JPanel();//初始化面板
jmb=new JMenuBar();//初始化菜单栏组件
jta=new JTextArea(50,50);//初始化文本域
jta.getDocument().addDocumentListener(
//给文本域注册监听器,用来监听文档是否发生更改,DocumentListener()接口中有三个方法
new DocumentListener() {
@Override//表示继承,以下三个方法是对父类方法的一个重写
public void insertUpdate(DocumentEvent e) {
wasSaved=false;//表示编辑框有修改操作
//当监听到有这三种操作时就代表着文本将重新保存,这时文本状态是未保存的,所以用false,true是文件已保存
}
@Override
public void removeUpdate(DocumentEvent e) {
wasSaved=false;//表示对编辑框有插入操作
}
@Override
public void changedUpdate(DocumentEvent e) {
wasSaved=false;//表示对编辑框内容有删除的操作
}
}
);
jsp=new JScrollPane(jta);// 给文本域添加滚动条
//下面对三个菜单按钮进行定义
file=new JMenu("File");//第一个,file菜单
JMenuItem item;//定义菜单项
file.add(item=new JMenuItem("New"));//给file添加以下功能
item.addActionListener(this);
file.add(item=new JMenuItem("Open..."));
item.addActionListener(this);
file.addSeparator();//调用该方法,在这两个功能下添加一条下划线
file.add(item=new JMenuItem("Save"));
item.addActionListener(this);
file.add(item=new JMenuItem("Save As..."));
item.addActionListener( this);
file.addSeparator();//调用该方法,添加一条下划线
file.add(item=new JMenuItem("Quit"));
item.addActionListener( this);
//给edit菜单添加以下功能
edit=new JMenu("Edit");
edit.add(item=new JMenuItem("Find..."));
item.addActionListener( this);
edit.add(item=new JMenuItem("Replace..."));
item.addActionListener(this);
//给view菜单添加以下功能
view=new JMenu("View");
view.add(item=new JMenuItem("Font..."));
item.addActionListener(this);
view.add(item=new JMenuItem("Color..."));
item.addActionListener(this);
}
public void init(){ //菜单栏和窗体的添加
jmb.add(file);//把三个菜单都添加到菜单栏组件上去
jmb.add(edit);
jmb.add(view);
this.setJMenuBar(jmb);//再设置jmb 为窗体的菜单栏,这个this指的是jp
this.add(jsp, BorderLayout.CENTER);//把带有滚动条的文本域添加到面板中间,这个this也是指jp
setSize(800,600);//窗体大小设置
jta.setFont(new Font("宋体",Font.PLAIN,18));//字体设置
setVisible(true);//窗口可见
}
public void actionPerformed(ActionEvent e){//该方法是对每个菜单事件的监听
String command=e.getActionCommand();//获得点击按钮的字符串
//getSource得到的组件的名称,而getActionCommand得到的是标签。
if(command.equals("Open...")){
File f=null;
openFile(f);
currentFile=f;
return;
}
if(command.equals("Color...")){
//Color菜单处理
Color c=JColorChooser.showDialog(this,"选择文字颜色",Color.BLACK);
jta.setForeground(c);//对文字进行颜色设置
return;
}
if(command.equals("Quit")){
this.dispose(); //关闭gui页面,关闭窗体并释放一部分窗体所占资源
}
if(command.equals("Save As...")){
File f = null;
saveFileAs(f);
currentFile=f;
return;
}
if(command.equals("Save")){
File f=null;
saveFile(f);
currentFile = f;
return;
}
}
//文件保存~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void saveFile(File f){
// 从标题栏取得文件名称
File file = new File(getTitle());
// 若指定的文件不存在
if(!file.exists()) {
// 执行另存为
saveFileAs(file);
}
else {
try {
// 开启指定的文件,创建一个字符输出缓冲流,让用户输入数据
BufferedWriter buf = new BufferedWriter(new FileWriter(file));
// 将文字编辑区的文字写入文件,
buf.write(jta.getText());
buf.close();//关闭缓冲流
}
catch(IOException e) {
JOptionPane.showMessageDialog(null, e.toString(),
"写入文件失败", JOptionPane.ERROR_MESSAGE);
}
}
}
private void saveFileAs(File f) {
// 显示文件对话框
JFileChooser fileChooser = new JFileChooser();//创建文件选择器
int option = fileChooser.showSaveDialog(null);//show‘’保存‘’
//showSaveDialog(null);----show‘’保存‘’
//showOpenDialog(null);----show“打开”
// 如果确认选取文件
if(option == JFileChooser.APPROVE_OPTION) {
//JFileChooser.APPROVE_OPTION是个整型常量,代表0。就是说当返回0的值我们才执行相关操作,否则什么也不做。
// 取得选择的文件
File file = fileChooser.getSelectedFile();
// 在标题栏上设定文件名称
setTitle(file.toString());
try {
// 建立文件
file.createNewFile();
// 进行文件保存
saveFile(file);
}
catch(IOException e) {
JOptionPane.showMessageDialog(null, e.toString(),
"无法建立新文件", JOptionPane.ERROR_MESSAGE);
}
}
}
//文件打开~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void openFile(File f){
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Open file");
int option=fileChooser.showDialog(null, null);
// 使用者按下确认键
if(option == JFileChooser.APPROVE_OPTION) {
try {
// 开启选取的文件
BufferedReader buf =new BufferedReader(new FileReader(fileChooser.getSelectedFile()));
// 设定文件标题
setTitle(fileChooser.getSelectedFile().toString());
// 清除前一次文件
clearjta();
// 取得系统相依的换行字符
String lineSeparator = System.getProperty("line.separator");//获取系统参数
// 读取文件并附加至文字编辑区
String text;//定义文本
while((text = buf.readLine()) != null) {
jta.append(text);
jta.append(lineSeparator);
}
buf.close();
}
catch(IOException e) {
JOptionPane.showMessageDialog(null, e.toString(),
"开启文件失败", JOptionPane.ERROR_MESSAGE);
}
}
}
private void clearjta() {
jta.selectAll();
jta.replaceSelection("");
}
public static void main(String[] args){
EasyTXT tx=new EasyTXT();
tx.TextEditor();
tx.init();
}
}
这里也顺便记录一下关于setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)方法,上述代码没有用到:
没有设置的话,默认点关闭时只是隐藏窗体,在后台进程中还可以看到,如果有多个窗口,只是销毁调用dispose的窗口,其他窗口仍然存在,整个应用程序还是处于运行状态。