记事本有很多功能,本小节将讲解其中较为重要的功能的实现过程。

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节:记事本功能实现相关推荐

  1. stm32l0的停止模式怎么唤醒_探索者 STM32F407 开发板资料连载第二十二章 待机唤醒实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第二十二章 待机唤醒实 ...

  2. stm32 文件系统dma大小_「正点原子NANO STM32F103开发板资料连载」第二十二章 DMA 实验...

    1)实验平台:[正点原子] NANO STM32F103 开发板 2)摘自<正点原子STM32 F1 开发指南(NANO 板-HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 ...

  3. 【正点原子MP157连载】第二十二章 新字符设备驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  4. 数字图像处理:第二十二章 基于模型的编码

    第二十二章基于模型的编码 目录 引言 基于对象的编码 基于模型的编码 作业 1. 引言 为了获得更高的压缩效率并保持一定的视频质量以支持超低码率(大约10kbps)双向视频应用,不考虑内容特点的仅仅针 ...

  5. DayDayUp:《机器崛起前传》第二十二章【蹒跚而来】读后感(文章源自网络)—听课笔记

    DayDayUp:<机器崛起前传>第二十二章[蹒跚而来]读后感(文章源自网络)-听课笔记 <机器崛起前传> 1.机器岂不能有自我?         计算机的发展历程可谓蹒跚.从 ...

  6. 第二十二章 5为你的命名空间取个别名

    //第二十二章 5为你的命名空间取个别名 /*#include <iostream> using namespace std; namespace people_compay_boss { ...

  7. 第二十二章 6未命名的命名空间

    //第二十二章 6未命名的命名空间 /*#include <iostream> using namespace std; namespace {int x=2; } namespace { ...

  8. 第二十二章:洗净皮衣

    第二十二章:洗净皮衣 一种心态,希望找到,另外一种心态,不希望找到,两种心态相互的交织着,让李二陛下的内心相当的痛苦. "你又在这里胡思乱想呢."这个时候长孙皇后走了过来,对着李二 ...

  9. 20190925 On Java8 第二十二章 枚举

    第二十二章 枚举 基本 enum 特性 创建 enum 时,编译器会为你生成一个相关的类,这个类继承自 Java.lang.Enum. valueOf() 是在 Enum 中定义的 static 方法 ...

  10. 第二十二章 SQL命令 CREATE TRIGGER(二)

    文章目录 第二十二章 SQL命令 CREATE TRIGGER(二) SQL触发器代码 ObjectScript触发代码 字段引用和伪字段引用 引用流属性 引用SQLComputed属性 标签 方法调 ...

最新文章

  1. 读书笔记 | 墨菲定律(一)
  2. C++ 指针运算符( 和 *) 终于讲明白了
  3. SAP MM 初阶之事务代码MIGO中采购退货的处理
  4. 理解HTTP session原理及应用
  5. 【图像分割应用】医学图像分割(二)——心脏分割
  6. 2021技术领域趋势报告:Rust继续增长、低代码是重要趋势
  7. java的math类_Java之Math类使用小结
  8. mysql and 优化_MySQL 优化(六)
  9. Java中,native2ascii.exe 的使用(最简单说明)
  10. edius裁剪快捷键_edius常用的快捷键有哪些-怎么设置快捷键-edius快捷键使用大全...
  11. YYText 源码剖析:CoreText 与异步绘制
  12. vscode返回快捷键
  13. 用切片实现一个简陋的Map
  14. 随便谈谈IT行业的几个定律
  15. 【分析BMI指数~python】
  16. 2021恒生电子面经(校招实习)
  17. python可以连续赋值吗_Python连续赋值的两个要点
  18. 运动学模型(二)----轮速计 后轮速差模型
  19. 产品经理:来做个APP根据用户手机壳颜色来改变主题颜色
  20. pdf转换器1.0注册码

热门文章

  1. 百度内部培训资料PPT:数据分析的道与术
  2. lasergrbl调整XYZA各轴电机运动方向
  3. 简介一:低延迟交易架构技术研究
  4. 【题解】NOI Online 2022 数学游戏题解
  5. 全选主元高斯消去法 matlab程序,[VB]全选主元高斯消去法求解线性方程组
  6. Ubuntu20文件系统磁盘空间不足low disk space on filesystem root
  7. TSDB写入与查询讲解,聚合(aggregator)与采样(downsample)讲解—以opentsdb为例
  8. Pytorch Lightning 之 amp_level
  9. 线性时不变系统的卷积
  10. 张一鸣:给产品技术人才的建议