第二十二章《记事本》第2节:记事本功能实现
记事本有很多功能,本小节将讲解其中较为重要的功能的实现过程。
22.2.1初始化菜单
记事本界面上最多的就是菜单和菜单项。如果在窗体上添加菜单,先要添加一个菜单栏。在Swing体系中,用JMenuBar类表示菜单栏,创建菜单栏的语句如下:
JMenuBar mainMenuBar=new JMenuBar();
创建菜单栏、给菜单栏添加菜单、给菜单添加菜单项以及给菜单项添加监听器的操作全部集中在createMenu()方法中实现,而createMenu()方法又在专门初始化组件的init()方法中被调用,以下是createMenu()方法的实现过程。
public void createMenu(){//创建JMenuBarmainMenuBar=new JMenuBar();//创建四个JMenufileMenu=new JMenu("文件");editMenu=new JMenu("编辑");formatMenu=new JMenu("格式");helpMenu=new JMenu("帮助");//创建JMenuItem并添加到对应的JMenu中mainMenuBar.add(fileMenu);newItem=new JMenuItem("新建");openItem=new JMenuItem("打开..");saveItem=new JMenuItem("保存..");saveasItem=new JMenuItem("另存为..");pageItem=new JMenuItem("页面设置..");printItem=new JMenuItem("打印..");exitItem=new JMenuItem("退出");fileMenu.add(newItem);fileMenu.add(openItem);fileMenu.add(saveItem);fileMenu.add(saveasItem);fileMenu.addSeparator();fileMenu.add(pageItem);fileMenu.add(printItem);fileMenu.addSeparator();fileMenu.add(exitItem);mainMenuBar.add(editMenu);undoItem=new JMenuItem("撤消");cutItem=new JMenuItem("剪切");copyItem=new JMenuItem("复制");pasteItem=new JMenuItem("粘贴");findItem=new JMenuItem("查找..");replaceItem=new JMenuItem("替换..");selectallItem=new JMenuItem("全选");dateItem=new JMenuItem("时间/日期");editMenu.add(undoItem);editMenu.addSeparator();editMenu.add(cutItem);editMenu.add(copyItem);editMenu.add(pasteItem);editMenu.addSeparator();editMenu.add(findItem);editMenu.add(replaceItem);editMenu.addSeparator();editMenu.add(selectallItem);editMenu.add(dateItem);mainMenuBar.add(formatMenu);wrapItem=new JCheckBoxMenuItem("自动换行");fontItem=new JMenuItem("设置字体..");formatMenu.add(wrapItem);formatMenu.add(fontItem);mainMenuBar.add(helpMenu);helpItem=new JMenuItem("帮助主题");aboutItem=new JMenuItem("关于..");helpMenu.add(helpItem);helpMenu.add(aboutItem);//给菜单项添加监听器exitItem.addActionListener(listener);saveItem.addActionListener(listener);saveasItem.addActionListener(listener);newItem.addActionListener(listener);printItem.addActionListener(listener);openItem.addActionListener(listener);cutItem.addActionListener(listener);copyItem.addActionListener(listener);pasteItem.addActionListener(listener);selectallItem.addActionListener(listener);dateItem.addActionListener(listener);wrapItem.addActionListener(listener);findItem.addActionListener(listener);fontItem.addActionListener(listener);
}
22.2.2保存功能
当用户单击“保存”菜单项时,程序必须完成以下操作:
- 判断文件是否为新文件,如果是新文件调用doSaveAs()方法实现保存操作。
- 如果不是新文件,查看上次保存之后是否有过修改操作,如果有修改操作直接以原文件名保存,否则调用doSaveAs()方法进行保存。
- 如果没有任何修改,则不需要做任何操作。
与保存相关的操作基本都由doSaveAs()方法完成的,doSaveAs()方法的实现过程如下:
int doSaveAs(){FileOutputStream fout;byte content[];int flag=0;File tmpfile=null;ExampleFileFilter filter = new ExampleFileFilter();JFileChooser chooser;filter.addExtension("txt");filter.setDescription("文本文件");if (file!=null){chooser = new JFileChooser(file.getPath());}else{chooser = new JFileChooser();}chooser.setFileFilter(filter);flag = chooser.showSaveDialog(this);if(flag == JFileChooser.APPROVE_OPTION) {tmpfile=chooser.getSelectedFile();if (tmpfile.exists()){if (JOptionPane.showConfirmDialog(this,"文件已经存在,是否覆盖?", "警告",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){flag=1;}else{flag=0;}}else{flag=1;}}else{flag=0;}if (flag==1){//用户已经确定要以指定名称保存文件try{fout=new FileOutputStream(tmpfile);content=text.getText().getBytes();fout.write(content);fout.close();flag = 1;}catch(FileNotFoundException e){JOptionPane.showMessageDialog(this,"指定的文件名称或属性有问题!");flag = 0;}catch(IOException e){JOptionPane.showMessageDialog(this,"无法写文件,请检查文件是否被锁定");flag = 0;}}if (flag==1){//文件保存成功,修改相关变量changed=false;haveName=true;file=tmpfile;this.setTitle("记事本 -- "+file.getName());}return flag;
}
22.2.3打开功能
当用户单击“打开”菜单项时,程序应完成以下操作:
- 判断当前文件是否被修改过,如果修改过则询问用户是否要保存当前文件。
- 如果用户选择“取消”则关闭对话框,否则弹出文件选择对话框由用户选择要打开的文件。
- 读入用户选择的文件内容,并把这些内容显示到窗体的文本区text中。
打开操作主要调用doOpen()方法完成,其实现过程如下:
//打开一个已经存在的文件
void doOpen(){int select,flag;File tmpfile=null;ExampleFileFilter filter;JFileChooser chooser;FileInputStream fin;byte buf[];if (changed){select=JOptionPane.showConfirmDialog(this,"文件修改后尚未存盘,要保存吗?");switch (select){case JOptionPane.YES_OPTION:flag=doSave();break;case JOptionPane.NO_OPTION:flag=1;break;default:flag=0;break;}}else{flag = 1;}if(flag==1){changed = false;filter = new ExampleFileFilter();filter.addExtension("txt");filter.setDescription("文本文件");if (file!=null){chooser = new JFileChooser(file.getPath());}else{chooser = new JFileChooser();}chooser.setFileFilter(filter);select = chooser.showOpenDialog(this);if(select == JFileChooser.APPROVE_OPTION) {tmpfile=chooser.getSelectedFile();try{fin=new FileInputStream(tmpfile);buf=new byte[(int)tmpfile.length()];fin.read(buf);fin.close();text.setText(new String(buf));changed=false;haveName=true;file=tmpfile;setTitle("记事本 -- "+file.getName());}catch(FileNotFoundException e){JOptionPane.showMessageDialog(this,"指定的文件名称或属性有问题!");}catch(IOException e){JOptionPane.showMessageDialog(this,"无法读文件,请检查文件是否被锁定");}}}
}
22.2.4全选、剪切、复制和粘贴文本
一般情况下,用户如果没有选择文本,那么剪切和复制菜单项应处于不可用状态,而一旦用户选择了一段文本,则这两个菜单项就应该立刻变成可用状态。
为实现这种效果,应该为文本区添加两个监听器,分别是键盘监听器和鼠标监听器。在本案例的程序代码中以适配器类的子类作为监听器的实现类,并且这两个监听器类被定义为内部类。这两个监听器主要监听文档是否发生了修改,其实现过程如下:
//键盘监听器类
class HandleKey extends KeyAdapter {public void keyPressed(KeyEvent e) {chkText();}
}//鼠标监听器类
class HandleMouse extends MouseAdapter {public void mouseReleased(MouseEvent e) {chkText();}
}//根据用户选择文本的情况,修改菜单的状态
void chkText() {if (text.getSelectedText() == null) {cutItem.setEnabled(false);copyItem.setEnabled(false);} else {cutItem.setEnabled(true);copyItem.setEnabled(true);}
}
全选功能由doSelectAll()方法实现,其代码如下:
//全选
void doSelectAll() {text.selectAll();
}
有了前面的准备工作,复制文本变得很简单,只需要调用doCopy()方法就能实现,其代码如下:
//将用户选择的文本复制到剪贴板
void doCopy() {text.copy();
}
同样的,实现剪切操作也很简单,只需要调用doCut()方法就能实现,其代码如下:
//将用户选择的文本复制到剪贴板
void doCut() {text.cut();
}
粘贴功能由doPaste()方法实现,其代码如下:
//将剪贴板中的内容复制到文本区
void doPaste() {text.paste();
}
22.2.5打印功能
Java的打印API主要存在于java.awt.print包下,而JDK1.4新增的与打印相关的类则在javax.print包以及它的子包javax.print和javax.print.event和javax.print.attribute中。
要实现打印操作,需要完成以下几个步骤:
- 定位一台打印机
- 指定打印内容的格式
- 设置打印属性
- 设置内容
- 打印
其中第三步一般通过一个对话框完成,从JDK1.4开始ServiceUI打印对话框,其界面如图22-4所示。
图22-4打印属性对话框
打印操作由doPrint()方法完成,其实现过程如下:
//调用打印对话框,给用户打印文档
void doPrint() {try {PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();PrintService service = null;service=ServiceUI.printDialog(null, 100, 100, printService, defaultService, flavor, pras);if (service != null) {DocPrintJob job = service.createPrintJob();DocAttributeSet das = new HashDocAttributeSet();Doc doc = new SimpleDoc(text.getText().getBytes(), flavor, das);job.print(doc, pras); //进行文件的打印}} catch (Exception e) {JOptionPane.showMessageDialog(this, "打印任务无法完成");}
}
22.2.6查找功能
查找功能对话框由FindDialog类实现,它是对话框类JDialog的子类。由于查找时是在查找对话框中设置关键字并且在NoteBookFrame类表示文本区的text组件中完成。从界面上来看,text是一个文本区,而从代码的角度来看text是NoteBookFrame的属性。为了访问这个属性,可以通过构造方法的参数把这个属性传递给FindDialog类对象,这样当找到关键字时就能操作这个text组件,因此FindDialog类的构造方法应设计为:
public FindDialog(JFrame owner, JTextArea text) {super(owner,false);init(text);
}
如果能找到关键字,则调用text的select()方法选中关键字,如果找不到关键字,则弹出一个对话框提示用户。限于篇幅,查找对话框的实现过程暂不给出,而在22.3小节的项目完整代码中一并给出。
22.2.7设置字体功能
设置字体对话框由FontDialog类表示,FontDialog也是JDialog的子类。设置字体对话框的界面如图22-2所示,从图中可以看出:对话框中有三个列表框,用户可以在这三个列表框中分别选择字体、字形和大小,当单击“确定”按钮后就能修改记事本中的字体。
在程序中,打开设置字体对话框的方法是doChangeFont(),其实现过程如下:
//设置字体
void doChangeFont() {if (myFontDialog == null) {myFontDialog = new FontDialog(this);}if (myFontDialog.showFontDialog() == FontDialog.OK) {text.setFont(myFontDialog.getFont());//获得对话框返回的字体并以它作为记事本字体}
}
22.2.8退出记事本
当用户单击“退出”菜单项时,程序应该完成以下操作。
- 如果文件已经被保存,则直接退出。
- 如果文件没有被保存,则弹出对话框询问用户是否要保存文件。
- 如果用户选择不保存,则直接退出。
- 如果用户选择取消,则关闭对话框。
为了完成以上操作,需要定义两个关键的boolean型变量:
- changed:用来标识文件是否已经被修改。
- haveName:用来标识文件是否有名字,实际上也是标识文件是不是新文件。
退出操作由doExit()方法完成,其实现过程如下:
//退出记事本
void doExit() {int select;if (!changed)System.exit(0);else {select = JOptionPane.showConfirmDialog(this, "文件修改后尚未保存,要保存吗?");switch (select) {case JOptionPane.YES_OPTION:select = doSave();if (select == 1) {System.exit(0);}break;case JOptionPane.NO_OPTION:System.exit(0);break;case JOptionPane.CANCEL_OPTION:break;}}
}
除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!
第二十二章《记事本》第2节:记事本功能实现相关推荐
- stm32l0的停止模式怎么唤醒_探索者 STM32F407 开发板资料连载第二十二章 待机唤醒实验
1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第二十二章 待机唤醒实 ...
- stm32 文件系统dma大小_「正点原子NANO STM32F103开发板资料连载」第二十二章 DMA 实验...
1)实验平台:[正点原子] NANO STM32F103 开发板 2)摘自<正点原子STM32 F1 开发指南(NANO 板-HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 ...
- 【正点原子MP157连载】第二十二章 新字符设备驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- 数字图像处理:第二十二章 基于模型的编码
第二十二章基于模型的编码 目录 引言 基于对象的编码 基于模型的编码 作业 1. 引言 为了获得更高的压缩效率并保持一定的视频质量以支持超低码率(大约10kbps)双向视频应用,不考虑内容特点的仅仅针 ...
- DayDayUp:《机器崛起前传》第二十二章【蹒跚而来】读后感(文章源自网络)—听课笔记
DayDayUp:<机器崛起前传>第二十二章[蹒跚而来]读后感(文章源自网络)-听课笔记 <机器崛起前传> 1.机器岂不能有自我? 计算机的发展历程可谓蹒跚.从 ...
- 第二十二章 5为你的命名空间取个别名
//第二十二章 5为你的命名空间取个别名 /*#include <iostream> using namespace std; namespace people_compay_boss { ...
- 第二十二章 6未命名的命名空间
//第二十二章 6未命名的命名空间 /*#include <iostream> using namespace std; namespace {int x=2; } namespace { ...
- 第二十二章:洗净皮衣
第二十二章:洗净皮衣 一种心态,希望找到,另外一种心态,不希望找到,两种心态相互的交织着,让李二陛下的内心相当的痛苦. "你又在这里胡思乱想呢."这个时候长孙皇后走了过来,对着李二 ...
- 20190925 On Java8 第二十二章 枚举
第二十二章 枚举 基本 enum 特性 创建 enum 时,编译器会为你生成一个相关的类,这个类继承自 Java.lang.Enum. valueOf() 是在 Enum 中定义的 static 方法 ...
- 第二十二章 SQL命令 CREATE TRIGGER(二)
文章目录 第二十二章 SQL命令 CREATE TRIGGER(二) SQL触发器代码 ObjectScript触发代码 字段引用和伪字段引用 引用流属性 引用SQLComputed属性 标签 方法调 ...
最新文章
- 读书笔记 | 墨菲定律(一)
- C++ 指针运算符( 和 *) 终于讲明白了
- SAP MM 初阶之事务代码MIGO中采购退货的处理
- 理解HTTP session原理及应用
- 【图像分割应用】医学图像分割(二)——心脏分割
- 2021技术领域趋势报告:Rust继续增长、低代码是重要趋势
- java的math类_Java之Math类使用小结
- mysql and 优化_MySQL 优化(六)
- Java中,native2ascii.exe 的使用(最简单说明)
- edius裁剪快捷键_edius常用的快捷键有哪些-怎么设置快捷键-edius快捷键使用大全...
- YYText 源码剖析:CoreText 与异步绘制
- vscode返回快捷键
- 用切片实现一个简陋的Map
- 随便谈谈IT行业的几个定律
- 【分析BMI指数~python】
- 2021恒生电子面经(校招实习)
- python可以连续赋值吗_Python连续赋值的两个要点
- 运动学模型(二)----轮速计 后轮速差模型
- 产品经理:来做个APP根据用户手机壳颜色来改变主题颜色
- pdf转换器1.0注册码
热门文章
- 百度内部培训资料PPT:数据分析的道与术
- lasergrbl调整XYZA各轴电机运动方向
- 简介一:低延迟交易架构技术研究
- 【题解】NOI Online 2022 数学游戏题解
- 全选主元高斯消去法 matlab程序,[VB]全选主元高斯消去法求解线性方程组
- Ubuntu20文件系统磁盘空间不足low disk space on filesystem root
- TSDB写入与查询讲解,聚合(aggregator)与采样(downsample)讲解—以opentsdb为例
- Pytorch Lightning 之 amp_level
- 线性时不变系统的卷积
- 张一鸣:给产品技术人才的建议