如果已有一段文本A,要从中找出字符串B首次出现的位置,我们可以采用暴力穷举的BF算法或者快速匹配的KMP算法。当然,最简单的就是调用已有的函数,在java中有以下两个函数:

从头向尾查找:

A.indexOf(String/char B, int fromIndex): 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
注:B类型为字符或字符串;查找区域为[fromIndex,end];返回索引是字符在字符串中的索引,与fromIndex无关;若不传入fromIndex参数,查找区域为[0,end]

从尾向头查找:

A.lastIndexOf(String/char B, int fromIndex): 返回指定子字符串在此字符串中最后一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
注:B类型为字符或字符串;查找区域为[0,fromIndex];返回索引是字符在字符串中的索引,与fromIndex无关;若不传入fromIndex参数,查找区域为[0,end]

要查找出文本A中字符串B出现的所有位置,只需要不断修改搜索开始位置fromIndex直至到达结束位置。

要在记事本中实现查找功能,则上述问题就变成了在文本区域JTextArea的文本中搜索我们在查找窗口输入的查找内容。因此,我们只需要获取文本区域的文本,以及查找内容文本框中的文本,就转化成了文章开头的问题。为便于理解,各组件的定义如下:

JTextArea jtext = new JTextArea();//文本区域
JDialog findDialog=new JDialog(this,"查找",false);//查找窗体
JTextField findText = new JTextField(); ;//查找内容输入文本框
JButton findNextButton = new JButton("查找下一个(F):");//查找下一个按钮
JButton cancel=new JButton("取消");//取消按钮
JCheckBox matchCheckBox = new JCheckBox("区分大小写(C)");//区分大小写复选框
JRadioButton upButton = new JRadioButton("向上(U)");//向上按钮
JRadioButton downButton = new JRadioButton("向下(U)");//向下按钮

要实现的功能为选中向下按钮,则由光标所在位置从头到尾查找,选中向上按钮则从尾向头查找;点击查找下一个按钮则在文本区域显示下一个匹配的字符,若没有可以匹配的字符,则弹出窗口提醒。

要做到点击按钮然后执行相应的操作,我们需要对点击按钮这一事件进行监听。为此,我们设置了查找下一个按钮的点击命令,并专门写了个menuhandler类来处理点击事件。

findNextButton.setActionCommand("findnext");//点击事件触发命令
findNextButton.addActionListener(menuhandler);

该类实现了ActionListener接口,对其中的actionPerformed函数进行重写。

public class MenuHandler implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e){
        String actionCommand = e.getActionCommand();//获取触发事件的命令
        if("findnext".equals(actionCommand){
            /*如果触发事件命令与我们为查找下一个按钮设置的命令相同
            那么我们就要执行这一部分所写的操作
            */
        }
    }
}

在操作部分,首先我们需要获取文本和待查找文本,查找的形式:向上,向下,是否区分大小写

String str1,str2,strA,strB;
Boolean up,down,checkbox;
str1=jtext.getText();//文本区域文本
str2=findText.getText();//查找窗口输入的查找内容
//选中返回true,未选中返回false
up=upButton.isSelected();//向上按钮是否选中
down=downButton.isSelected();//向下按钮是否选中
checkbox=matchCheckBox.isSelected();//区分大小写复选框是否选中

如果不需要区分大小写,我们可以将文本和待查找文本均转为大写或小写。

if(checkbox)//区分大小写的JCheckBox被选中,采用原有文本
{   strA=str1;  
    strB=str2;
}  
else//不区分大小写,采用转化成大写的文本  
{   strA=str1.toUpperCase();//文本区域文本转为大写  
    strB=str2.toUpperCase();//查找文本转为大写 
} 

此时再根据向上、向下按钮的选择情况进行相应的查找操作。在讲解查找操作之前,我先说明一下在文本区域中光标位置下标和字符位置下标之间的关系。如图:

其中短下划线是光标,圆圈是字符,两者的下标是相互独立的,上图中光标的下标为[0,6],字符的下标为[0,5],相同下标的光标在字符的前一位。向indexOf和lastIndexOf函数传入的参数是按字符下标来查找的。

向下查找时光标选中内容时位置后移不影响继续查找。

if(down)  
{   //getCaretPosition()为获取光标在文本区域中的位置下标  
    k=strA.indexOf(strB,jtext.getCaretPosition());      
    if(k>-1)//无匹配内容时K==-1 
    {   
        jtext.setCaretPosition(k);//设置光标位置
        jtext.select(k,k+strB.length());//选中内容,此时光标位置后移了strB.length()长度  
    }  
    else  
        JOptionPane.showMessageDialog(null,"找不到\""+str2+"\"","记事本",JOptionPane.INFORMATION_MESSAGE);//弹出提醒框   
}

showMessageDialog参数说明:

参数1:显示对话框的框架,为null则使用默认框架

参数2:对话框中的内容

参数3:对话框标题

参数4:信息类型1.错误信息(INFORMATION_MESSAGE)

2.警告信息(QUESTION_MESSAGE / PLAIN_MESSAGE)

上述提醒框窗口如图:

向上查找时光标选中内容位置后移要返回选中前的位置。

if(up)  
{      
    if(jtext.getSelectedText()==null)
        //光标与其后一个字符位置下标相同,在光标前的内容中查找要-1
        k=strA.lastIndexOf(strB,jtext.getCaretPosition()-1);
    else
        k=strA.lastIndexOf(strB, jtext.getCaretPosition()-strB.length()-1);
    if(k>-1)//查找内容存在
    {    
        jtext.setCaretPosition(k);//设置光标位置
        jtext.select(k,k+strB.length());//选中内容,此时光标位置后移了strB.length()长度
    }  
    else  
        JOptionPane.showMessageDialog(null,"找不到\""+str2+"\"","记事本",JOptionPane.INFORMATION_MESSAGE);   
}

同理,对于取消按钮的点击事件处理也是设置事件命令、处理事件。

cancel.setActionCommand("findcancel");
cancel.addActionListener(menuhandler);
if("findcancel".equals(actionCommand)){
    findDialog.dispose();//直接关闭查找窗口
}

以下是我为记事本做的一些简便的操作,即在文本区域选中部分文本,然后点击查找下一个就会显示下一个匹配的文本,其实就是将输入的查找内容变为文本区域选中的文本,查找上一个也可以这样。

if("fastfindnext".equals(actionCommand)){
    int k=0;  
    String str1,str2;
    str1=jtext.getText();
    //如果没有选中文本作为查找内容,则弹出提醒框,不进行后续查找操作
    if(jtext.getSelectedText()==null){
        JOptionPane.showMessageDialog(null,"请用光标从左向右选中待查找内容","提醒",JOptionPane.INFORMATION_MESSAGE);
        return;
    }
    str2=jtext.getSelectedText();//获取选中的内容 
    k=str1.indexOf(str2,jtext.getCaretPosition());      
    if(k>-1)  
    {   
        jtext.setCaretPosition(k);
        jtext.select(k,k+str2.length());  
    }  
    else  
        JOptionPane.showMessageDialog(null,"找不到\""+str2+"\"","记事本",JOptionPane.INFORMATION_MESSAGE);    
}

最后,再讲一下如何为某一个按钮的点击或者菜单的打开设置快捷键,我了解到的有以下两种方式。

组件名.setAccelerator(KeyStroke.getKeyStroke("ctrl A"));
组件名.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0,KeyEvent.CTRL_MASK));

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐