I have a quick question about implementing my SpellChecker into my Swing Text Editor. I tried to search around but couldn't find anything on how to get the red squiggly line under misspelled words. Is there something I could import then call on those misspellings? Also, how would I be able to make a menu pop up when I right-click on those miss spelled words? Thanks
Asked
Active
Viewed 443 times
-1
-
You would have to draw the red wiggly lines. There are word lists you can use to check word spelling, A JDialog could show the possible words. http://www.gwicks.net/dictionaries.htm – Gilbert Le Blanc Jul 28 '20 at 19:09
2 Answers
3
There is plenty of material out there depending on what you want to do...
First of, use a JTextPane
, which supports nice text formatting options.
How to underline text:
Comments are included as explanations.
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);
});
}
}
How to pop a menu on word selection:
Comments are included as explanations.
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);
});
}
}
Resources and references:
- How to Use Editor Panes and Text Panes
- clickable text from jTextPane
- making text underline font by using JTextPane?
- How to get selection from JTextPane
- How to clear all styling from StyledDocument?
- Getting 'Attempt to mutate notification' exception
- How do I set different colors for text and underline in JTextPane?
- Underline StyleConstant in a different colour with AttributeSet
- Deselect selected text in JTextPane

gthanop
- 3,035
- 2
- 10
- 27
1
how to get the red squiggly line under misspelled words.
You can highlight the text and use a custom Painter to draw the red squiggly line.
Check out the Squiggle Painter for the custom painting code.
Basic usage would be:
SquigglePainter red = new SquigglePainter( Color.RED );
try
{
textField.getHighlighter().addHighlight( ?, ?, red );
}
catch(BadLocationException ble) {}
where the "?" would be the start/end offset of the text you want to underline.

camickr
- 321,443
- 19
- 166
- 288