在JTextArea中高亮显示下一个上一个比赛的JButton JAVA SWING

问题描述 投票:0回答:1

我正试图在我的Java Swing应用程序中实现在JTextArea中搜索特定单词的按钮。谁能帮我实现高亮显示下一个和上一个匹配的按钮?请查看我的searchbutton的代码。现在它工作得很好。

PS.我想在新的应用程序中运行searchButton。我想在new Thread中运行searchButton。这样可以吗?

searchButton.addActionListener(e -> new Thread(() -> {
        int pos = 0;
        // Get the text to find...convert it to lower case for eaiser comparision
        String find = searchField.getText().toLowerCase();
        // Focus the text area, otherwise the highlighting won't show up
        textArea.requestFocusInWindow();
        // Make sure we have a valid search term
        if (find != null && find.length() > 0) {
            Document document = textArea.getDocument();
            int findLength = find.length();
            try {
                boolean found = false;
                // Rest the search position if we're at the end of the document
                if (pos + findLength > document.getLength()) {
                    pos = 0;
                }
                // While we haven't reached the end...
                // "<=" Correction
                while (pos + findLength <= document.getLength()) {
                    // Extract the text from the docuemnt
                    String match = document.getText(pos, findLength).toLowerCase();
                    // Check to see if it matches or request
                    if (match.equals(find)) {
                        found = true;
                        break;
                    }
                    pos++;
                }
                // Did we find something...
                if (found) {
                    // Get the rectangle of the where the text would be visible...
                    Rectangle viewRect = textArea.modelToView(pos);
                    // Scroll to make the rectangle visible
                    textArea.scrollRectToVisible(viewRect);
                    // Highlight the text
                    textArea.setCaretPosition(pos + findLength);
                    textArea.select(pos, pos + findLength);
                    textArea.grabFocus();

                }

            } catch (Exception exp) {
                exp.printStackTrace();
            }
        }
    }));
java swing jbutton jtextfield jtextarea
1个回答
0
投票
  1. 不要使用线程。你只在耗时的任务中使用线程。搜索一个文本字符串不是一个耗时的任务。另外,Swing组件的更新需要在EDT上完成。所以你希望高亮显示是在EDT上完成的。

  2. 不要使用 grabFocus()。你已经使用了 requestFocusInWindow(),这是正确的方法。

  3. 使用 String.indexOf(…) 方法(如@ControlAltDel所建议)。那么就不需要循环代码了。你只需要从当前的斜线位置搜索文本,你要么找到这个词,要么找不到。

就其价值而言,我正好有一些旧的代码可以做到这一点。

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

public class TextComponentFindNext extends JFrame implements ActionListener
{
    JTextComponent textComponent;
    JTextField textField;

    public TextComponentFindNext()
        throws Exception
    {
        textComponent = new JTextPane();
        JScrollPane scrollPane = new JScrollPane( textComponent );
        scrollPane.setPreferredSize( new Dimension(500, 400) );
        getContentPane().add(scrollPane, BorderLayout.NORTH);

        textField = new JTextField(10);
        textField.setText("im");
        textField.addActionListener( this );
        getContentPane().add(textField, BorderLayout.WEST);

        JButton button = new JButton("Find Next");
        button.addActionListener( this );
        getContentPane().add(button, BorderLayout.EAST);

        FileReader reader = new FileReader( "TextComponentFindNext.java" );
        BufferedReader br = new BufferedReader(reader);
        textComponent.read(br, null);
        br.close();
    }

    public void actionPerformed(ActionEvent e)
    {
        String searchString = "";

        //  this works
        try
        {
            Document doc = textComponent.getDocument();
            searchString = doc.getText(0, doc.getLength());
        }
        catch(BadLocationException ble) {}

        //  this doesn't work
//      searchString = textComponent.getText();

        int offset = textComponent.getCaretPosition();
        String searchText = textField.getText();

        int start = searchString.indexOf(searchText, offset);

        if (start != -1)
        {
            textComponent.select(start, start + searchText.length());
            textComponent.requestFocusInWindow();
        }
    }

    public static void main(String[] args)
        throws Exception
    {
        JFrame frame = new TextComponentFindNext();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}

不需要滚动逻辑,当文本被选中时,它会自动滚动。

如果你想在滚动时玩点花样,你可以将包含文本的行 "居中"。请看 文本工具 以获得一些允许你这样做的辅助方法。

注意,最好是从Document中获取文本,而不是组件。从Document中获取的文本只包含一个"\n "字符串作为行尾字符串。这意味着它将同时适用于JTextArea和JTextPane。请看。文本和新行 获取更多信息。


1
投票

有两种方法可以在你的JTextArea中搜索匹配的文本。

  1. 使用String.indexOf(idx) [forward]和String.lastIndexOf(idx) [backward]来搜索文档文本,其中: idx 是当前的小数点位置,也可以使用String.toUppercase toLowercase对搜索文本和文档文本进行大小写区分。如果您不想让搜索结果区分大小写,您也可以在搜索文本和文档文本上使用String.toUppercase toLowercase。

  2. 使用MatcherPattern进行正则表达式搜索。这是更强大但更复杂的解决方案。顺便说一下,我正在努力推出一个DHTML解决方案,很长时间以来,我都想加入正则搜索。但最终我没有这样做--我认为客户(除非他们是内部也许)并不关心学习如何编写regex的问题

© www.soinside.com 2019 - 2024. All rights reserved.