• 第二十二章《记事本》第2节:记事本功能实现


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

    22.2.1初始化菜单

    记事本界面上最多的就是菜单和菜单项。如果在窗体上添加菜单,先要添加一个菜单栏。在Swing体系中,用JMenuBar类表示菜单栏,创建菜单栏的语句如下:

    JMenuBar mainMenuBar=new JMenuBar();

    创建菜单栏、给菜单栏添加菜单、给菜单添加菜单项以及给菜单项添加监听器的操作全部集中在createMenu()方法中实现,而createMenu()方法又在专门初始化组件的init()方法中被调用,以下是createMenu()方法的实现过程。

    1. public void createMenu(){
    2.     //创建JMenuBar
    3.     mainMenuBar=new JMenuBar();
    4.     //创建四个JMenu
    5.     fileMenu=new JMenu("文件");
    6.     editMenu=new JMenu("编辑");
    7.     formatMenu=new JMenu("格式");
    8.     helpMenu=new JMenu("帮助");
    9.     //创建JMenuItem并添加到对应的JMenu中
    10.     mainMenuBar.add(fileMenu);
    11.     newItem=new JMenuItem("新建");
    12.     openItem=new JMenuItem("打开..");
    13.     saveItem=new JMenuItem("保存..");
    14.     saveasItem=new JMenuItem("另存为..");
    15.     pageItem=new JMenuItem("页面设置..");
    16.     printItem=new JMenuItem("打印..");
    17.     exitItem=new JMenuItem("退出");
    18.     fileMenu.add(newItem);
    19.     fileMenu.add(openItem);
    20.     fileMenu.add(saveItem);
    21.     fileMenu.add(saveasItem);
    22.     fileMenu.addSeparator();
    23.     fileMenu.add(pageItem);
    24.     fileMenu.add(printItem);
    25.     fileMenu.addSeparator();
    26.     fileMenu.add(exitItem);
    27.     mainMenuBar.add(editMenu);
    28.     undoItem=new JMenuItem("撤消");
    29.     cutItem=new JMenuItem("剪切");
    30.     copyItem=new JMenuItem("复制");
    31.     pasteItem=new JMenuItem("粘贴");
    32.     findItem=new JMenuItem("查找..");
    33.     replaceItem=new JMenuItem("替换..");
    34.     selectallItem=new JMenuItem("全选");
    35.     dateItem=new JMenuItem("时间/日期");
    36.     editMenu.add(undoItem);
    37.     editMenu.addSeparator();
    38.     editMenu.add(cutItem);
    39.     editMenu.add(copyItem);
    40.     editMenu.add(pasteItem);
    41.     editMenu.addSeparator();
    42.     editMenu.add(findItem);
    43.     editMenu.add(replaceItem);
    44.     editMenu.addSeparator();
    45.     editMenu.add(selectallItem);
    46.     editMenu.add(dateItem);
    47.     mainMenuBar.add(formatMenu);
    48.     wrapItem=new JCheckBoxMenuItem("自动换行");
    49.     fontItem=new JMenuItem("设置字体..");
    50.     formatMenu.add(wrapItem);
    51.     formatMenu.add(fontItem);
    52.     mainMenuBar.add(helpMenu);
    53.     helpItem=new JMenuItem("帮助主题");
    54.     aboutItem=new JMenuItem("关于..");
    55.     helpMenu.add(helpItem);
    56.     helpMenu.add(aboutItem);
    57.     //给菜单项添加监听器
    58.     exitItem.addActionListener(listener);
    59.     saveItem.addActionListener(listener);
    60.     saveasItem.addActionListener(listener);
    61.     newItem.addActionListener(listener);
    62.     printItem.addActionListener(listener);
    63.     openItem.addActionListener(listener);
    64.     cutItem.addActionListener(listener);
    65.     copyItem.addActionListener(listener);
    66.     pasteItem.addActionListener(listener);
    67.     selectallItem.addActionListener(listener);
    68.     dateItem.addActionListener(listener);
    69.     wrapItem.addActionListener(listener);
    70.     findItem.addActionListener(listener);
    71.     fontItem.addActionListener(listener);
    72. }

    22.2.2保存功能

    当用户单击“保存”菜单项时,程序必须完成以下操作:

    • 判断文件是否为新文件,如果是新文件调用doSaveAs()方法实现保存操作。
    • 如果不是新文件,查看上次保存之后是否有过修改操作,如果有修改操作直接以原文件名保存,否则调用doSaveAs()方法进行保存。
    • 如果没有任何修改,则不需要做任何操作。

    与保存相关的操作基本都由doSaveAs()方法完成的,doSaveAs()方法的实现过程如下:

    1. int doSaveAs(){
    2.     FileOutputStream fout;
    3.     byte content[];
    4.     int flag=0;
    5.     File tmpfile=null;
    6.     ExampleFileFilter filter = new ExampleFileFilter();
    7.     JFileChooser  chooser;
    8.     filter.addExtension("txt");
    9.     filter.setDescription("文本文件");
    10.     if (file!=null){
    11.         chooser = new JFileChooser(file.getPath());
    12.     }
    13.     else{
    14.         chooser =  new JFileChooser();
    15.     }
    16.     chooser.setFileFilter(filter);
    17.     flag = chooser.showSaveDialog(this);
    18.     if(flag == JFileChooser.APPROVE_OPTION) {
    19.         tmpfile=chooser.getSelectedFile();
    20.         if (tmpfile.exists()){
    21.             if (JOptionPane.showConfirmDialog(this,"文件已经存在,是否覆盖?", "警告",
    22.                JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){
    23.                     flag=1;
    24.             }else{
    25.                 flag=0;
    26.             }
    27.         }else{
    28.             flag=1;
    29.         }
    30.     }else{
    31.         flag=0;
    32.     }
    33.     if (flag==1){//用户已经确定要以指定名称保存文件
    34.         try{
    35.             fout=new FileOutputStream(tmpfile);
    36.             content=text.getText().getBytes();
    37.             fout.write(content);
    38.             fout.close();
    39.             flag = 1;
    40.         }catch(FileNotFoundException e){
    41.             JOptionPane.showMessageDialog(this,"指定的文件名称或属性有问题!");
    42.             flag = 0;
    43.         }catch(IOException e){
    44.             JOptionPane.showMessageDialog(this,"无法写文件,请检查文件是否被锁定");
    45.             flag = 0;
    46.         }
    47.     }
    48.     if (flag==1){//文件保存成功,修改相关变量
    49.         changed=false;
    50.         haveName=true;
    51.         file=tmpfile;
    52.         this.setTitle("记事本 -- "+file.getName());
    53.     }
    54.     return flag;
    55. }

    22.2.3打开功能

    当用户单击“打开”菜单项时,程序应完成以下操作:

    • 判断当前文件是否被修改过,如果修改过则询问用户是否要保存当前文件。
    • 如果用户选择“取消”则关闭对话框,否则弹出文件选择对话框由用户选择要打开的文件。
    • 读入用户选择的文件内容,并把这些内容显示到窗体的文本区text中。

    打开操作主要调用doOpen()方法完成,其实现过程如下:

    1. //打开一个已经存在的文件
    2. void doOpen(){
    3.     int select,flag;
    4.     File tmpfile=null;
    5.     ExampleFileFilter filter;
    6.     JFileChooser chooser;
    7.     FileInputStream fin;
    8.     byte    buf[];
    9.     if (changed){
    10.         select=JOptionPane.showConfirmDialog(this,"文件修改后尚未存盘,要保存吗?");
    11.         switch (select){
    12.             case JOptionPane.YES_OPTION:
    13.                 flag=doSave();
    14.                 break;
    15.             case JOptionPane.NO_OPTION:
    16.                 flag=1;
    17.                 break;
    18.             default:
    19.                 flag=0;
    20.                 break;
    21.         }
    22.     }else{
    23.         flag = 1;
    24.     }
    25.     if(flag==1){
    26.         changed = false;
    27.         filter = new ExampleFileFilter();
    28.         filter.addExtension("txt");
    29.         filter.setDescription("文本文件");
    30.         if (file!=null){
    31.             chooser =  new JFileChooser(file.getPath());
    32.         }
    33.         else{
    34.             chooser =  new JFileChooser();
    35.         }
    36.         chooser.setFileFilter(filter);
    37.         select = chooser.showOpenDialog(this);
    38.         if(select == JFileChooser.APPROVE_OPTION) {
    39.             tmpfile=chooser.getSelectedFile();
    40.             try{
    41.                 fin=new FileInputStream(tmpfile);
    42.                 buf=new byte[(int)tmpfile.length()];
    43.                 fin.read(buf);
    44.                 fin.close();
    45.                 text.setText(new String(buf));
    46.                 changed=false;
    47.                 haveName=true;
    48.                 file=tmpfile;
    49.                 setTitle("记事本 -- "+file.getName());
    50.             }catch(FileNotFoundException e){
    51.                 JOptionPane.showMessageDialog(this,"指定的文件名称或属性有问题!");
    52.             }catch(IOException e){
    53.                 JOptionPane.showMessageDialog(this,"无法读文件,请检查文件是否被锁定");
    54.             }
    55.         }
    56.     }
    57. }

    22.2.4全选、剪切、复制和粘贴文本

    一般情况下,用户如果没有选择文本,那么剪切和复制菜单项应处于不可用状态,而一旦用户选择了一段文本,则这两个菜单项就应该立刻变成可用状态。

    为实现这种效果,应该为文本区添加两个监听器,分别是键盘监听器和鼠标监听器。在本案例的程序代码中以适配器类的子类作为监听器的实现类,并且这两个监听器类被定义为内部类。这两个监听器主要监听文档是否发生了修改,其实现过程如下:

    1. //键盘监听器类
    2. class HandleKey extends KeyAdapter {
    3.     public void keyPressed(KeyEvent e) {
    4.         chkText();
    5.     }
    6. }
    7. //鼠标监听器类
    8. class HandleMouse extends MouseAdapter {
    9.     public void mouseReleased(MouseEvent e) {
    10.         chkText();
    11.     }
    12. }
    13. //根据用户选择文本的情况,修改菜单的状态
    14. void chkText() {
    15.     if (text.getSelectedText() == null) {
    16.         cutItem.setEnabled(false);
    17.         copyItem.setEnabled(false);
    18.     } else {
    19.         cutItem.setEnabled(true);
    20.         copyItem.setEnabled(true);
    21.     }
    22. }

    全选功能由doSelectAll()方法实现,其代码如下:

    1. //全选
    2. void doSelectAll() {
    3.     text.selectAll();
    4. }

    有了前面的准备工作,复制文本变得很简单,只需要调用doCopy()方法就能实现,其代码如下:

    1. //将用户选择的文本复制到剪贴板
    2. void doCopy() {
    3.    text.copy();
    4. }

    同样的,实现剪切操作也很简单,只需要调用doCut()方法就能实现,其代码如下:

    1. //将用户选择的文本复制到剪贴板
    2. void doCut() {
    3.     text.cut();
    4. }

    粘贴功能由doPaste()方法实现,其代码如下:

    1. //将剪贴板中的内容复制到文本区
    2. void doPaste() {
    3.     text.paste();
    4. }

    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()方法完成,其实现过程如下:

    1. //调用打印对话框,给用户打印文档
    2. void doPrint() {
    3.     try {
    4.         PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
    5.         DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
    6.         PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
    7.         PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
    8.         PrintService service = null;
    9.         service=ServiceUI.printDialog(null, 100, 100, printService, defaultService, flavor, pras);
    10.         if (service != null) {
    11.             DocPrintJob job = service.createPrintJob();
    12.             DocAttributeSet das = new HashDocAttributeSet();
    13.             Doc doc = new SimpleDoc(text.getText().getBytes(), flavor, das);
    14.             job.print(doc, pras); //进行文件的打印
    15.         }
    16.     } catch (Exception e) {
    17.         JOptionPane.showMessageDialog(this, "打印任务无法完成");
    18.     }
    19. }

    22.2.6查找功能

    查找功能对话框由FindDialog类实现,它是对话框类JDialog的子类。由于查找时是在查找对话框中设置关键字并且在NoteBookFrame类表示文本区的text组件中完成。从界面上来看,text是一个文本区,而从代码的角度来看text是NoteBookFrame的属性。为了访问这个属性,可以通过构造方法的参数把这个属性传递给FindDialog类对象,这样当找到关键字时就能操作这个text组件,因此FindDialog类的构造方法应设计为:

    1. public FindDialog(JFrame owner, JTextArea text) {
    2.     super(owner,false);
    3.     init(text);
    4. }

    如果能找到关键字,则调用text的select()方法选中关键字,如果找不到关键字,则弹出一个对话框提示用户。限于篇幅,查找对话框的实现过程暂不给出,而在22.3小节的项目完整代码中一并给出。

    22.2.7设置字体功能

    设置字体对话框由FontDialog类表示,FontDialog也是JDialog的子类。设置字体对话框的界面如图22-2所示,从图中可以看出:对话框中有三个列表框,用户可以在这三个列表框中分别选择字体、字形和大小,当单击“确定”按钮后就能修改记事本中的字体。

    在程序中,打开设置字体对话框的方法是doChangeFont(),其实现过程如下:

    1. //设置字体
    2. void doChangeFont() {
    3.     if (myFontDialog == null) {
    4.         myFontDialog = new FontDialog(this);
    5.     }
    6.     if (myFontDialog.showFontDialog() == FontDialog.OK) {
    7.         text.setFont(myFontDialog.getFont());//获得对话框返回的字体并以它作为记事本字体
    8.     }
    9. }

    22.2.8退出记事本

    当用户单击“退出”菜单项时,程序应该完成以下操作。

    • 如果文件已经被保存,则直接退出。
    • 如果文件没有被保存,则弹出对话框询问用户是否要保存文件。
    • 如果用户选择不保存,则直接退出。
    • 如果用户选择取消,则关闭对话框。

    为了完成以上操作,需要定义两个关键的boolean型变量:

    • changed:用来标识文件是否已经被修改。
    • haveName:用来标识文件是否有名字,实际上也是标识文件是不是新文件。

    退出操作由doExit()方法完成,其实现过程如下:

    1. //退出记事本
    2. void doExit() {
    3.     int select;
    4.     if (!changed)
    5.         System.exit(0);
    6.     else {
    7.         select = JOptionPane.showConfirmDialog(this, "文件修改后尚未保存,要保存吗?");
    8.         switch (select) {
    9.             case JOptionPane.YES_OPTION:
    10.                 select = doSave();
    11.                 if (select == 1) {
    12.                     System.exit(0);
    13.                 }
    14.                 break;
    15.             case JOptionPane.NO_OPTION:
    16.                 System.exit(0);
    17.                 break;
    18.             case JOptionPane.CANCEL_OPTION:
    19.                 break;
    20.         }
    21.     }
    22. }

    除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!

  • 相关阅读:
    Spark部署模式与作业提交
    基于AlexNet卷积神经网络的手写体数字识别系统研究-附Matlab代码
    基于离散、连续、线性和非线性模型进行模型预测(MPC)控制(Matlab代码实现)
    Django-Import-Export插件控制数据导入流程
    token
    PyQt5快速开发与实战 9.3 Pandas在PyQt中的应用
    C++多态
    跟着pink老师前端入门教程(JavaScript)-day05
    计算机毕业设计源码基于SSM的古风古韵二手家具交易系统程序+数据库
    基于3D分层卷积融合的多模态生理信号情绪识别
  • 原文地址:https://blog.csdn.net/shalimu/article/details/128149719