JButton, который выделяет следующий / предыдущий матч в JTextArea JAVA SWING - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь реализовать кнопки, которые ищут определенное c слово в JTextArea в моем Java приложении Swing. Может кто-нибудь помочь мне реализовать кнопки для выделения следующего и предыдущего матча? Пожалуйста, просмотрите мой код для кнопки поиска. На данный момент все отлично работает.

PS. Я хочу запустить 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();
            }
        }
    }));

Ответы [ 2 ]

1 голос
/ 22 апреля 2020

Существует два способа поиска по тексту совпадений в JTextArea:

  1. Используйте String.indexOf (idx) [forward] и String.lastIndexOf (idx) [backward] в тексте документа, где idx - текущее местоположение каретки. Вы также можете использовать String.toUppercase / toLowercase как для текста поиска, так и для текста документа, если не хотите, чтобы при поиске учитывался регистр.

  2. Использовать Matcher / Pattern для поиск по регулярному выражению. Это более мощное, но сложное решение. И только к вашему сведению, я работаю над развертыванием решения D HTML и очень долго хотел включить поиск по регулярным выражениям. Но, в конце концов, я не стал - я не думаю, что клиенты (если они не внутренние) заботятся о том, чтобы научиться писать регулярные выражения

0 голосов
/ 22 апреля 2020
  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);
    }
}

Нет необходимости в логике прокрутки c, это будет прокручиваться автоматически при выделении текста.

Если вы хотите поиграться с прокруткой, вы можете «центрировать» строку, содержащую текст. Проверьте Утилиты текста , чтобы узнать о некоторых вспомогательных методах, которые позволяют вам это делать.

Обратите внимание, что лучше получать текст из документа, а не из компонентов. Текст из документа содержит только строку "\ n" для конца строки. Это означает, что он будет работать как для JTextArea, так и для JTextPane. См. Текст и новые строки для получения дополнительной информации.

...