【環(huán)球速看料】第二十二章《記事本》第2節(jié):記事本功能實(shí)現(xiàn)

2023-01-05 14:28:36 來(lái)源:51CTO博客

?記事本有很多功能,本小節(jié)將講解其中較為重要的功能的實(shí)現(xiàn)過(guò)程。

22.2.1初始化菜單

記事本界面上最多的就是菜單和菜單項(xiàng)。如果在窗體上添加菜單,先要添加一個(gè)菜單欄。在Swing體系中,用JMenuBar類表示菜單欄,創(chuàng)建菜單欄的語(yǔ)句如下:?


(資料圖片僅供參考)

JMenuBar mainMenuBar=new JMenuBar();?

創(chuàng)建菜單欄、給菜單欄添加菜單、給菜單添加菜單項(xiàng)以及給菜單項(xiàng)添加監(jiān)聽(tīng)器的操作全部集中在createMenu()方法中實(shí)現(xiàn),而createMenu()方法又在專門(mén)初始化組件的init()方法中被調(diào)用,以下是createMenu()方法的實(shí)現(xiàn)過(guò)程。?

public void createMenu(){    //創(chuàng)建JMenuBar    mainMenuBar=new JMenuBar();    //創(chuàng)建四個(gè)JMenu    fileMenu=new JMenu("文件");    editMenu=new JMenu("編輯");    formatMenu=new JMenu("格式");    helpMenu=new JMenu("幫助");    //創(chuàng)建JMenuItem并添加到對(duì)應(yīng)的JMenu中    mainMenuBar.add(fileMenu);    newItem=new JMenuItem("新建");    openItem=new JMenuItem("打開(kāi)..");    saveItem=new JMenuItem("保存..");    saveasItem=new JMenuItem("另存為..");    pageItem=new JMenuItem("頁(yè)面設(shè)置..");    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("復(fù)制");    pasteItem=new JMenuItem("粘貼");    findItem=new JMenuItem("查找..");    replaceItem=new JMenuItem("替換..");    selectallItem=new JMenuItem("全選");    dateItem=new JMenuItem("時(shí)間/日期");    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("自動(dòng)換行");    fontItem=new JMenuItem("設(shè)置字體..");    formatMenu.add(wrapItem);    formatMenu.add(fontItem);    mainMenuBar.add(helpMenu);    helpItem=new JMenuItem("幫助主題");    aboutItem=new JMenuItem("關(guān)于..");    helpMenu.add(helpItem);    helpMenu.add(aboutItem);    //給菜單項(xiàng)添加監(jiān)聽(tīng)器    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保存功能

當(dāng)用戶單擊“保存”菜單項(xiàng)時(shí),程序必須完成以下操作:?

判斷文件是否為新文件,如果是新文件調(diào)用doSaveAs()方法實(shí)現(xiàn)保存操作。?如果不是新文件,查看上次保存之后是否有過(guò)修改操作,如果有修改操作直接以原文件名保存,否則調(diào)用doSaveAs()方法進(jìn)行保存。?如果沒(méi)有任何修改,則不需要做任何操作。?

與保存相關(guān)的操作基本都由doSaveAs()方法完成的,doSaveAs()方法的實(shí)現(xiàn)過(guò)程如下:?

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,"文件已經(jīng)存在,是否覆蓋?",               "警告",               JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){                    flag=1;            }else{                flag=0;            }        }else{            flag=1;        }    }else{        flag=0;    }    if (flag==1){//用戶已經(jīng)確定要以指定名稱保存文件        try{            fout=new FileOutputStream(tmpfile);            content=text.getText().getBytes();            fout.write(content);            fout.close();            flag = 1;        }catch(FileNotFoundException e){            JOptionPane.showMessageDialog(this,"指定的文件名稱或?qū)傩杂袉?wèn)題!");            flag = 0;        }catch(IOException e){            JOptionPane.showMessageDialog(this,"無(wú)法寫(xiě)文件,請(qǐng)檢查文件是否被鎖定");            flag = 0;        }    }    if (flag==1){//文件保存成功,修改相關(guān)變量        changed=false;        haveName=true;        file=tmpfile;        this.setTitle("記事本 -- "+file.getName());    }    return flag;}

22.2.3打開(kāi)功能

當(dāng)用戶單擊“打開(kāi)”菜單項(xiàng)時(shí),程序應(yīng)完成以下操作:?

判斷當(dāng)前文件是否被修改過(guò),如果修改過(guò)則詢問(wèn)用戶是否要保存當(dāng)前文件。?如果用戶選擇“取消”則關(guān)閉對(duì)話框,否則彈出文件選擇對(duì)話框由用戶選擇要打開(kāi)的文件。?讀入用戶選擇的文件內(nèi)容,并把這些內(nèi)容顯示到窗體的文本區(qū)text中。?

打開(kāi)操作主要調(diào)用doOpen()方法完成,其實(shí)現(xiàn)過(guò)程如下:?

//打開(kāi)一個(gè)已經(jīng)存在的文件void doOpen(){    int select,flag;    File tmpfile=null;    ExampleFileFilter filter;    JFileChooser chooser;    FileInputStream fin;    byte    buf[];    if (changed){        select=JOptionPane.showConfirmDialog(this,"文件修改后尚未存盤(pán),要保存嗎?");        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,"指定的文件名稱或?qū)傩杂袉?wèn)題!");            }catch(IOException e){                JOptionPane.showMessageDialog(this,"無(wú)法讀文件,請(qǐng)檢查文件是否被鎖定");            }        }    }}

22.2.4全選、剪切、復(fù)制和粘貼文本

一般情況下,用戶如果沒(méi)有選擇文本,那么剪切和復(fù)制菜單項(xiàng)應(yīng)處于不可用狀態(tài),而一旦用戶選擇了一段文本,則這兩個(gè)菜單項(xiàng)就應(yīng)該立刻變成可用狀態(tài)。?

為實(shí)現(xiàn)這種效果,應(yīng)該為文本區(qū)添加兩個(gè)監(jiān)聽(tīng)器,分別是鍵盤(pán)監(jiān)聽(tīng)器和鼠標(biāo)監(jiān)聽(tīng)器。在本案例的程序代碼中以適配器類的子類作為監(jiān)聽(tīng)器的實(shí)現(xiàn)類,并且這兩個(gè)監(jiān)聽(tīng)器類被定義為內(nèi)部類。這兩個(gè)監(jiān)聽(tīng)器主要監(jiān)聽(tīng)文檔是否發(fā)生了修改,其實(shí)現(xiàn)過(guò)程如下:

//鍵盤(pán)監(jiān)聽(tīng)器類class HandleKey extends KeyAdapter {    public void keyPressed(KeyEvent e) {        chkText();    }}//鼠標(biāo)監(jiān)聽(tīng)器類class HandleMouse extends MouseAdapter {    public void mouseReleased(MouseEvent e) {        chkText();    }}//根據(jù)用戶選擇文本的情況,修改菜單的狀態(tài)void chkText() {    if (text.getSelectedText() == null) {        cutItem.setEnabled(false);        copyItem.setEnabled(false);    } else {        cutItem.setEnabled(true);        copyItem.setEnabled(true);    }}

全選功能由doSelectAll()方法實(shí)現(xiàn),其代碼如下:?

//全選?void doSelectAll() {?    text.selectAll();?}?

有了前面的準(zhǔn)備工作,復(fù)制文本變得很簡(jiǎn)單,只需要調(diào)用doCopy()方法就能實(shí)現(xiàn),其代碼如下:?

//將用戶選擇的文本復(fù)制到剪貼板?void doCopy() {?    text.copy();?}?

同樣的,實(shí)現(xiàn)剪切操作也很簡(jiǎn)單,只需要調(diào)用doCut()方法就能實(shí)現(xiàn),其代碼如下:?

//將用戶選擇的文本復(fù)制到剪貼板?void doCut() {?    text.cut();?}?

粘貼功能由doPaste()方法實(shí)現(xiàn),其代碼如下:?

//將剪貼板中的內(nèi)容復(fù)制到文本區(qū)?void doPaste() {?    text.paste();?}?

22.2.5打印功能

Java的打印API主要存在于java.awt.print包下,而JDK1.4新增的與打印相關(guān)的類則在javax.print包以及它的子包javax.print和javax.print.event和javax.print.attribute中。?

要實(shí)現(xiàn)打印操作,需要完成以下幾個(gè)步驟:?

定位一臺(tái)打印機(jī)?指定打印內(nèi)容的格式?設(shè)置打印屬性?設(shè)置內(nèi)容?打印?

其中第三步一般通過(guò)一個(gè)對(duì)話框完成,從JDK1.4開(kāi)始ServiceUI打印對(duì)話框,其界面如圖22-4所示。?

圖22-4打印屬性對(duì)話框?

打印操作由doPrint()方法完成,其實(shí)現(xiàn)過(guò)程如下:?

//調(diào)用打印對(duì)話框,給用戶打印文檔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); //進(jìn)行文件的打印        }    } catch (Exception e) {        JOptionPane.showMessageDialog(this, "打印任務(wù)無(wú)法完成");    }}

22.2.6查找功能

查找功能對(duì)話框由FindDialog類實(shí)現(xiàn),它是對(duì)話框類JDialog的子類。由于查找時(shí)是在查找對(duì)話框中設(shè)置關(guān)鍵字并且在NoteBookFrame類表示文本區(qū)的text組件中完成。從界面上來(lái)看,text是一個(gè)文本區(qū),而從代碼的角度來(lái)看text是NoteBookFrame的屬性。為了訪問(wèn)這個(gè)屬性,可以通過(guò)構(gòu)造方法的參數(shù)把這個(gè)屬性傳遞給FindDialog類對(duì)象,這樣當(dāng)找到關(guān)鍵字時(shí)就能操作這個(gè)text組件,因此FindDialog類的構(gòu)造方法應(yīng)設(shè)計(jì)為:?

public FindDialog(JFrame owner, JTextArea text) {?    super(owner,false);?    init(text);?}?

如果能找到關(guān)鍵字,則調(diào)用text的select()方法選中關(guān)鍵字,如果找不到關(guān)鍵字,則彈出一個(gè)對(duì)話框提示用戶。限于篇幅,查找對(duì)話框的實(shí)現(xiàn)過(guò)程暫不給出,而在22.3小節(jié)的項(xiàng)目完整代碼中一并給出。?

22.2.7設(shè)置字體功能

設(shè)置字體對(duì)話框由FontDialog類表示,F(xiàn)ontDialog也是JDialog的子類。設(shè)置字體對(duì)話框的界面如圖22-2所示,從圖中可以看出:對(duì)話框中有三個(gè)列表框,用戶可以在這三個(gè)列表框中分別選擇字體、字形和大小,當(dāng)單擊“確定”按鈕后就能修改記事本中的字體。?

在程序中,打開(kāi)設(shè)置字體對(duì)話框的方法是doChangeFont(),其實(shí)現(xiàn)過(guò)程如下:?

//設(shè)置字體?void doChangeFont() {?    if (myFontDialog == null) {?        myFontDialog = new FontDialog(this);?    }?    if (myFontDialog.showFontDialog() == FontDialog.OK) {?        text.setFont(myFontDialog.getFont());//獲得對(duì)話框返回的字體并以它作為記事本字體?    }?}?

22.2.8退出記事本

當(dāng)用戶單擊“退出”菜單項(xiàng)時(shí),程序應(yīng)該完成以下操作。?

如果文件已經(jīng)被保存,則直接退出。?如果文件沒(méi)有被保存,則彈出對(duì)話框詢問(wèn)用戶是否要保存文件。?如果用戶選擇不保存,則直接退出。?如果用戶選擇取消,則關(guān)閉對(duì)話框。?

為了完成以上操作,需要定義兩個(gè)關(guān)鍵的boolean型變量:?

changed:用來(lái)標(biāo)識(shí)文件是否已經(jīng)被修改。?haveName:用來(lái)標(biāo)識(shí)文件是否有名字,實(shí)際上也是標(biāo)識(shí)文件是不是新文件。?

退出操作由doExit()方法完成,其實(shí)現(xiàn)過(guò)程如下:?

//退出記事本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;        }    }}

本文字版教程還配有更詳細(xì)的視頻講解,小伙伴們可以??點(diǎn)擊這里??觀看。

標(biāo)簽: 設(shè)置字體 關(guān)閉對(duì)話框 打印對(duì)話框

上一篇:【數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)】Windows環(huán)境下MongoDB數(shù)據(jù)庫(kù)文件遷移后啟動(dòng)報(bào)錯(cuò)的數(shù)據(jù)恢復(fù)案例
下一篇:環(huán)球?qū)崟r(shí):桌面客戶端性能提升,優(yōu)化使用資源消耗