在 JTextArea JAVA SWING 中突出显示 next/previous 匹配项的 JButton
JButton that highlights next/previous match in JTextArea JAVA SWING
我正在尝试在我的 Java Swing 应用程序中实现在 JTextArea 中搜索特定单词的按钮。谁能帮我实现按钮来突出显示下一场和上一场比赛?请同时查看我的搜索按钮代码。现在它工作正常。
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();
}
}
}));
有两种方法可以在文本中搜索 JTextArea 中的匹配项:
在文档文本上使用 String.indexOf(idx) [forward] 和 String.lastIndexOf(idx) [backward],其中 idx
是当前插入符位置.如果您不希望搜索区分大小写,您可能还想在搜索文本和文档文本中使用 String.toUppercase / toLowercase。
使用Matcher/Pattern进行正则表达式搜索。这是更强大但更复杂的解决方案。仅供参考,我正在努力推出一个 DHTML 解决方案,并且在最长的时间内我想包括正则表达式搜索。但最后我没有——我认为客户(除非他们可能是内部的)不关心学习如何编写正则表达式
不要使用线程。您仅将 Thread 用于耗时的任务。搜索文本字符串不是一项耗时的任务。此外,需要在 EDT 上完成对 Swing 组件的更新。所以你希望突出显示在 EDT 上完成。
不要使用 grabFocus()。您已经使用了 requestFocusInWindow() ,这是正确的使用方法。
使用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);
}
}
不需要滚动逻辑,选中文本后会自动滚动。
如果您想要滚动,可以 "center" 包含文本的行。查看 Text Utilities 以获取一些帮助您执行此操作的方法。
注意,最好从文档中获取文本,而不是组件。文档中的文本仅包含一个“\n”字符串作为行尾字符串。这意味着它适用于 JTextArea 和 JTextPane。请参阅:Text and New Lines 了解更多信息。
我正在尝试在我的 Java Swing 应用程序中实现在 JTextArea 中搜索特定单词的按钮。谁能帮我实现按钮来突出显示下一场和上一场比赛?请同时查看我的搜索按钮代码。现在它工作正常。
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();
}
}
}));
有两种方法可以在文本中搜索 JTextArea 中的匹配项:
在文档文本上使用 String.indexOf(idx) [forward] 和 String.lastIndexOf(idx) [backward],其中
idx
是当前插入符位置.如果您不希望搜索区分大小写,您可能还想在搜索文本和文档文本中使用 String.toUppercase / toLowercase。使用Matcher/Pattern进行正则表达式搜索。这是更强大但更复杂的解决方案。仅供参考,我正在努力推出一个 DHTML 解决方案,并且在最长的时间内我想包括正则表达式搜索。但最后我没有——我认为客户(除非他们可能是内部的)不关心学习如何编写正则表达式
不要使用线程。您仅将 Thread 用于耗时的任务。搜索文本字符串不是一项耗时的任务。此外,需要在 EDT 上完成对 Swing 组件的更新。所以你希望突出显示在 EDT 上完成。
不要使用 grabFocus()。您已经使用了 requestFocusInWindow() ,这是正确的使用方法。
使用
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);
}
}
不需要滚动逻辑,选中文本后会自动滚动。
如果您想要滚动,可以 "center" 包含文本的行。查看 Text Utilities 以获取一些帮助您执行此操作的方法。
注意,最好从文档中获取文本,而不是组件。文档中的文本仅包含一个“\n”字符串作为行尾字符串。这意味着它适用于 JTextArea 和 JTextPane。请参阅:Text and New Lines 了解更多信息。