help.add(helpItem[i]);
text.setFont(newFont("system",0,14));
StringSelectionclipString=newStringSelection("");
clipbd.setContents(clipString,clipString);
//为菜单项添加监听器。
fileItem[0].addActionListener(newNewL());
fileItem[1].addActionListener(newOpenL());
fileItem[2].addActionListener(newSaveL());
fileItem[3].addActionListener(newSaveAsL());
fileItem[4].addActionListener(newExitL());
editItem[0].addActionListener(newCopyL());
editItem[1].addActionListener(newPasteL());
editItem[2].addActionListener(newCutL());
editItem[3].addActionListener(newAllselectL());
styleItem[0].addActionListener(newWrapL());
styleItem[1].addActionListener(newWrapL());
styleItem[2].addActionListener(newDateL());
setTitle("采摘器"+"--"+fileName);
}
用循环语句加入菜单项,以后增加菜单项时此处代码不用修改。
而加入菜单时不用 循环方法,而个别加入是为了程序易读,增加菜单的几率是比较小的。
加入main()方法后程序就可以运行了。
(先把添加监听器的这断代码注释掉!
)
publicstaticvoidmain(String[]args){
Notepadnpd=newNotepad();
npd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
npd.setSize(400,240);
npd.setVisible(true);
}
}
三菜单功能的实现
每一个菜单功能都需要为之建立一个监听器类,并重载活动监听方法addActionListener()。
㈠ 编辑菜单——复制、删除和粘贴
1复制
“编辑/复制”功能是把从文本区中选择的内容selection送到剪贴板clipbd中。
复制监听器类CopyL的代码如下:
classCopyLimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
Stringselection=text.getSelectedText();
if(selection=="")return;
StringSelectionclipString=newStringSelection(selection);
clipbd.setContents(clipString,clipString);
}
}
利用文本区的getSelectedText()方法获取你所选择的内容,存放在Notepad的字段(成员变量)selection中。
要把selection设置到剪贴板中,使用Clipboard类的setContents方法:
clipbd.setContents(clipString,clipString);
不要StringSelection类的对象作为参数,所以声明了
StringSelectionclipString=newStringSelection(selection);。
设置剪贴板内容的方法声明如下:
publicvoidsetContents(Transferable contents,ClipboardOwner owner)
它将剪贴板的当前内容设置到指定的transferable对象contents中,并将指定的剪贴板所有者owner作为新内容的所有者注册。
如果剪贴板当前不可用,则该方法抛出IllegalStateException。
例如,在某些平台上,系统剪贴板在被别的应用程序访问时是不可用的。
2删除
“编辑/删除”功能只要利用文本区的replaceRange方法,把选择的文本替换为空字符串。
监听器类CopyL的代码如下:
classCutLimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
Stringselection=text.getSelectedText();
if(selection=="")return;
StringSelectionclipString=newStringSelection(selection);
clipbd.setContents(clipString,clipString);
text.replaceRange("",text.getSelectionStart(),text.getSelectionEnd());
content=selection;
}
}
3粘贴
“编辑/粘贴”功能是把剪贴板中的数据来替换窗口中选择的内容,也要利用的replaceRange方法。
监听器类PasteL的代码如下:
classPasteLimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
ransferableclipData=clipbd.getContents(Notepad.this);
try{
StringclipString=(String)clipData.getTransferData(DataFlavor.stringFlavor);
text.replaceRange(clipString,text.getSelectionStart(),text.getSelectionEnd());
}catch(Exceptionex){
System.err.println("没有信息粘贴");
}
}
}
先从剪贴板中获取内容getContents(),返回的数据clipData是ransferable类型的。
因为需要使用该类型的方法getTransferData()方法把数据转化成字符串。
其参数DataFlavor.stringFlavor是DataFlavor的一个静态,表示JavaUnicodeString的字符串。
函数返回一个数据对象Object,所以要用强制转换。
使用该方法是可能会抛出一个异常的。
剪贴板和数据传输类ransferable都在包ava.awt.datatransfer中。
获得了选择的内容clipString,用一个replaceRange方法就把当前选择的内容替换成前面从剪贴板中获取的内容了。
如果当前没有选择内容,那么开始和结束位置相同,就把文本粘贴当光标位置了。
作为练习,请读者自行增加一个“撤消删除”和一个“剪切”的菜单功能。
㈡读入文件和保存文件
为了实现文件菜单的功能,在主类中先建立读写文件的方法read()和write()。
privatevoidread(Stringfile)throwsIOException{
Stringline="";
Stringstr="";
try{
BufferedReaderin=newBufferedReader(
newFileReader(file));
while((line=in.readLine())!
=null)
str+=(line+"\n");
content=str;
in.close();
}catch(IOExceptione){
e.printStackTrace();
System.exit
(1);
}
}
read(file)的功能是把文件file的内容按行读入储存在字段content中。
file是文件名也许在对话框中获得。
privatevoidwrite(Stringfile)throwsIOException{
try{
PrintWriterout=newPrintWriter(
newBufferedWriter(newFileWriter(file)));
out.write(content);
out.close();
return;
}catch(IOExceptione){
e.printStackTrace();
System.exit
(1);
}
}
write(file)的功能是把字段content写入到文件file中。
使用这两个方法是为了简化打开和保存文件的代码。
㈢文件菜单——打开、保存和另存为
1打开文件监听器
“文件/打开”菜单的主要功能是打开一个JAVA系统提供的文件对话框,它由类JFileChooser的方法showOpenDialog()来打开。
类似的,showSaveDialog()方法可打开保存文件的对话框。
classOpenLimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
try{
JFileChooserc=newJFileChooser();
intrVal=c.showOpenDialog(Notepad.this);
if(rVal==JFileChooser.APPROVE_OPTION){
fileName=c.getSelectedFile().getPath();
isNamed=true;
read(fileName);
text.setText(content);
setTitle("采摘器"+"--"+fileName);
return;
}
if(rVal==JFileChooser.CANCEL_OPTION)
return;
}catch(IOExceptionex){
ex.printStackTrace();
}
}
}
c.showOpenDialog(Notepad.this)方法中的参数类型是Component,代码中用参数Notepad.this表示主程序本身,意思就是从主窗口Frame打开的对话框。
它返回一个整数rVal,用来判断用户在对话框中选择的结果。
当你选择了一个存在的文件后,返回值是JFileChooser.APPROVE_OPTION,如果你放弃选择,那么返回值是JFileChooser.CANCEL_OPTION。
如果你选择了一个存在的文件名,用getSelectedFile()得到一个File类型对象,因此可以获取药打开的文件名,然后可调用read(fileName)方法读出文件到content中。
因为要使用文件的输入输出,所以可能会抛出IO异常。
2另存为监听器
“文件/另存为”菜单的功能是打开一个保存文件对话框,调用showSaveDialog方法获取文件名,用write(fileName)把content写进文件中。
同时要把 isNamed设置为true,为的是以后点“保存”菜单时不用再打开对话框。
classSaveAsLimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
try{
JFileChooserc=newJFileChooser();
intrVal=c.showSaveDialog(Notepad.this);
fileName=c.getSelectedFile().getPath();
if(rVal==JFileChooser.APPROVE_OPTION){
content=text.getText();//forinvocatewrite()
write(fileName);
isNamed=true;
setTitle("采摘器"+"--"+fileName);
}
if(rVal==JFileChooser.CANCEL_OPTION)
return;
}catch(IOExceptionex){
ex.printStackTrace();
}
}
}
3保存监听器
“文件/保存”菜单与另存为不同的是:
如果文件名已经有了(用isNamed=true表示),那就直接调用read方法读入文件,如果是未命名,那就打开保存文件对话框。
所以先使用了if(isNamed) write(fileName),其他与“另存为”的都一样。
classSaveLimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
try{
if(isNamed){
content=text.getText();
write(fileName);
}
else{//isNamedisfalse
JFileChooserc=newJFileChooser();
intrVal=c.showSaveDialog(Notepad.this);
fileName=c.getSelectedFile().getPath();
if(rVal==JFileChooser.APPROVE_OPTION){
content=text.getText();//forinvocatewrite()
write(fileName);
isNamed=true;
setTitle("采摘器"+"--"+fileName);
}
if(rVal==JFileChooser.CANCEL_OPTION)
return;
}//else
}catch(IOExceptionex){
ex.printStackTrace();
}
}
}
4“新建”监听器
新建文件时只提供一个空白的编辑区,文件名设为"未命名",可写入标记isNamed设为假,待写入内容content置为空白。
classNewLimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
text.setText("");
isNamed=false;
fileName="未命名";
content="";
setTitle("采摘器"+"--"+fileName);
}
}
四完整的源程序代码
//Notepad.java是一个记事本式的采摘器
importjavax.swing.*;
importjava.awt.*;
importjava.awt.event.*;
importjava.awt.datatransfer.*;
importjava.io.*;
importjava.util.*;
importjava.lang.String;
publicclassNotepadextendsJFrame{
privateJTextAreatext=newJTextArea(30,48);
privateJMenuBarmb=newJMenuBar();
privateClipboardclipbd=getToolkit().getSystemClipboard();
privateStringfileName="未命名";
privatebooleanisNamed=false;
privateStringcontent="";//为读写文件用
privateJMenu
file=newJMenu("文件"),
edit=newJMenu("编辑"),
style=newJMenu("格式"),
help=newJMenu("帮助");