java - Java Swing 拼写检查器
问题描述
我有一个关于在 Swing 文本编辑器中实现 SpellChecker 的快速问题。我试图四处搜索,但找不到任何关于如何在拼写错误的单词下获得红色波浪线的信息。有什么我可以导入然后调用那些拼写错误的东西吗?另外,当我右键单击那些拼写错误的单词时,如何弹出菜单?谢谢
解决方案
有很多材料取决于你想做什么......
首先,使用 a JTextPane
,它支持漂亮的文本格式选项。
如何给文字加下划线:
包括注释作为解释。
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
public class WordUnderline {
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final Style defaultStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
final JTextPane pane = new JTextPane();
//My super-creative text...
pane.setText("These are words...\nHere come more words!\nWord word word.");
final StyledDocument doc = pane.getStyledDocument();
doc.addDocumentListener(new DocumentListener() {
private void clearStyle(final DocumentEvent e) {
SwingUtilities.invokeLater(() -> doc.setCharacterAttributes(0, doc.getLength(), defaultStyle, true));
}
@Override
public void insertUpdate(final DocumentEvent e) {
//When you type a new letter, we want to (lets say) clear all the styles from the whole document...
clearStyle(e);
}
@Override
public void removeUpdate(final DocumentEvent e) {
//When you erase a letter, we want to (lets say) clear all styles from the whole document...
clearStyle(e);
}
@Override
public void changedUpdate(final DocumentEvent e) {
//When changing the style of the document, we want to do nothing else (but the change will happen).
}
});
final JButton doit = new JButton("Underline selected text!");
doit.addActionListener(e -> {
final SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setUnderline(sas, true);
/*I would suggest here to experiment a bit with the StyleConstants
class... For example: StyleConstants.setBackground(sas, Color.RED);*/
final int start = pane.getSelectionStart();
final int end = pane.getSelectionEnd();
doc.setCharacterAttributes(start, end - start, sas, true);
});
final JPanel contents = new JPanel(new BorderLayout());
contents.add(doit, BorderLayout.PAGE_START);
contents.add(pane, BorderLayout.CENTER);
final JFrame frame = new JFrame("Word underline.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(contents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
如何在单词选择上弹出菜单:
包括注释作为解释。
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
import javax.swing.text.Utilities;
public class WordPopUp {
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final JTextPane pane = new JTextPane();
//My super-creative text...
pane.setText("These are words...\nHere come more words!\nWord word word.");
pane.addMouseListener(new MouseAdapter() {
private boolean pendingPopUp = false; //Indicates whether we have already a popup popped up...
private void pop(final MouseEvent mevt) {
if (SwingUtilities.isRightMouseButton(mevt)) {
try {
final StyledDocument doc = pane.getStyledDocument();
//Get the location of the document where the user clicked:
final int offset = pane.viewToModel(mevt.getPoint());
//Find what word is at the location of the document where the user clicked:
final int start = Utilities.getWordStart(pane, offset),
end = Utilities.getWordEnd(pane, offset);
//Set the selection to be that word:
pane.setSelectionStart(start);
pane.setSelectionEnd(end);
//Obtain the value of the selected word:
final String word = doc.getText(start, end - start);
//Create the contents of the popup:
final JPanel popupPanel = new JPanel();
//Create the alternative words (via JButtons):
final int cnt = 4;
final ArrayList<JButton> words = new ArrayList<>();
for (int i = 0; i < cnt; ++i) {
final JButton button = new JButton(word + (i + 1));
popupPanel.add(button);
words.add(button);
}
final JButton cancel = new JButton("Cancel");
popupPanel.add(cancel);
//Create the popup itself:
final Popup popup = PopupFactory.getSharedInstance().getPopup(pane, popupPanel, mevt.getXOnScreen(), mevt.getYOnScreen());
//Hook action listenere to the word and cancel buttons:
words.forEach(button -> button.addActionListener(e -> {
try {
//Get the text of that button (it is going to be the new word):
final String newWord = ((JButton) e.getSource()).getText();
//Replace the old text with the new one:
doc.remove(start, end - start);
doc.insertString(start, newWord, null);
//Prepare caret position, so the user can keep on writing:
pane.setCaretPosition(start + newWord.length());
}
catch (final BadLocationException | RuntimeException x) {
JOptionPane.showMessageDialog(pane, "Oups!");
}
finally {
popup.hide();
pendingPopUp = false;
}
}));
//On cancel, deselect the selected text and close the popup:
cancel.addActionListener(e -> {
popup.hide();
pane.setSelectionStart(offset);
pane.setSelectionEnd(offset);
pendingPopUp = false;
});
pendingPopUp = true;
popup.show();
}
catch (final BadLocationException | RuntimeException x) {
JOptionPane.showMessageDialog(pane, "Oups! No word found?...");
}
}
}
private void maybePop(final MouseEvent mevt) {
if (mevt.isPopupTrigger()) {
if (pendingPopUp)
System.err.println("A popup is already popped. Close it to pop a new one.");
else
pop(mevt);
}
}
@Override
public void mouseClicked(final MouseEvent mevt) {
maybePop(mevt);
}
@Override
public void mousePressed(final MouseEvent mevt) {
maybePop(mevt);
}
@Override
public void mouseReleased(final MouseEvent mevt) {
maybePop(mevt);
}
});
final JFrame frame = new JFrame("Word underline.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(pane));
//Give some room to spare:
final Dimension dim = frame.getPreferredSize();
dim.width += 100;
dim.height += 100;
frame.setPreferredSize(dim);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
资源和参考:
推荐阅读
- circleci - 在 CircleCI 步骤中直接使用环境变量
- jquery - 不能在 jquery 函数中使用变量
- python - opencv和多处理导致管道损坏
- java - spring boot PAYTM API 集成?
- c++ - 为什么我在使用 getline() 时遇到问题?“没有重载函数的实例与参数列表匹配”和“数据不明确”
- html - 将正文放在一个列中,图像放在单独的右列中
- python - Python numpy.testing 中的不匹配
- vba - 将数据从多张表提取到一张表中
- excel - 无法从 WorkSheetFunction 类获取 VLookup 属性
- java-8 - 使用 Java 8 将复杂对象列表转换为 Map