【环球速看料】第二十二章《记事本》第2节:记事本功能实现

2023-01-05 14:28:36 来源:51CTO博客

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

22.2.1初始化菜单

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


(资料图片仅供参考)

JMenuBar mainMenuBar=new JMenuBar();​

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

public void createMenu(){    //创建JMenuBar    mainMenuBar=new JMenuBar();    //创建四个JMenu    fileMenu=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;        }    }}

本文字版教程还配有更详细的视频讲解,小伙伴们可以​​点击这里​​观看。

标签: 设置字体 关闭对话框 打印对话框

上一篇:【数据库数据恢复】Windows环境下MongoDB数据库文件迁移后启动报错的数据恢复案例
下一篇:环球实时:桌面客户端性能提升,优化使用资源消耗