0

I need to underline the selected word in my app either by just clicking the word or by selecting a piece of the text .

so my first idea was to use a JLabel because it parses the text as HTML but i didn't find out how to know the clicked word then i tried JEditorPane and it worked but not as excpected as i used a MouseListener mouseReleased() to underline the selected text.

  public void mouseReleased (MouseEvent e){
if (jEditorPane.getSelectedText()==null ||jEditorPane.getSelectedText().equals(""))
        return;
//to know the get real location of the text
//because by default the editorpane will add the rest of the html elements
// to the text to make look like a proper page
    int x1=jEditorPane.getText().indexOf("<body>")+"<body>".length();
    int x2=jEditorPane.getText().indexOf("</body>");
//the editor pane will add few white spaces after the body tag
    String trim = (jEditorPane.getText().subSequence(x1, x2)+"").trim();
    int selectionStart = jEditorPane.getSelectionStart();
    int selectionEnd = jEditorPane.getSelectionEnd();
    String text = trim;
    String beg = text.substring(0,selectionStart);
    String mid = "<U>"+text.substring(selectionStart,selectionEnd)+"</U>";
    String end = text.substring(selectionEnd,text.length());
    jEditorPane.setText(beg+mid+end);

}

the proplem is the selected text is not accurate ! some of my selection is underlined and some not , i need to make it accurate or to underline the clicked word and thank in advance .(JEditorPane is not necessary if you have a better idea)

  • `JEditorPane` supports a `StyledDocument`, I highly recommend looking to that - [for example](https://stackoverflow.com/questions/18948148/jeditorpane-set-foreground-color-for-different-words/18948340#18948340) - which changes the text color, but should give you basic idea – MadProgrammer Feb 13 '19 at 23:55
  • Possible duplicate [making text underline font by using JTextPane?](https://stackoverflow.com/questions/19414126/making-text-underline-font-by-using-jtextpane) – MadProgrammer Feb 14 '19 at 00:09
  • it's not duplicate , i know how to underline the text but what i want is to underline only the text selected by the user wich is not accurate in my code i don't know why. – a lovely person Feb 14 '19 at 00:13
  • Well, as far as I can see, you're not making use of the styled document, so, not really doing it the best way and calling `setText` would not be required if you used the `StyledDocument` so I'd say your approach is generally wrong to start with and the link would provide a bases for a good starting point - IMHO – MadProgrammer Feb 14 '19 at 00:25

1 Answers1

1

Based on making text underline font by using JTextPane? and How to get a point value for where a word (or selection) in a JTextArea is on the screen? I was able to produce ...

Underling text with the mouse

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.text.Utilities;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JEditorPane editorPane;

        public TestPane() {
            editorPane = new JEditorPane();
            editorPane.setContentType("text/html");
            editorPane.setText("<html>Hello world, this is a test</html>");
            setLayout(new BorderLayout());
            add(new JScrollPane(editorPane));

            editorPane.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    Point point = e.getPoint();
                    Range range = getRangeOfWordUnderMouse(editorPane, point);
                    //String word = getWordUnderMouse(editorPane, point);
                    SimpleAttributeSet as = new SimpleAttributeSet();
                    StyleConstants.setUnderline(as, true);
                    ((StyledDocument)editorPane.getDocument()).setCharacterAttributes(range.getFrom(), range.length(), as, false);
                }

            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public static class Range {
        private int from;
        private int to;

        public Range(int from, int to) {
            this.from = from;
            this.to = to;
        }

        public int getFrom() {
            return from;
        }

        public int getTo() {
            return to;
        }

        public int length() {
            return to - from;
        }

    }

    public static Range getRangeOfWordUnderMouse(JTextComponent textComp, Point2D point) {
        int pos = textComp.viewToModel2D(point);
        try {
            Document doc = textComp.getDocument();
            if (pos > 0 && (pos >= doc.getLength() || Character.isWhitespace(doc.getText(pos, 1).charAt(0)))) {
                // if the next character is a white space then use 
                // the word on the left side..
                pos--;
            }
            // get the word from current position
            final int begOffs = Utilities.getWordStart(textComp, pos);
            final int endOffs = Utilities.getWordEnd(textComp, pos);

            return new Range(begOffs, endOffs);
        } catch (BadLocationException ex) {
            // Ignore this exception!!!
            ex.printStackTrace();
        }
        return null;
    }

    public static String getWordUnderMouse(JTextComponent textComp, Point2D point) {
        Range range = getRangeOfWordUnderMouse(textComp, point);
        if (range == null) {
            return "";
        }

        try {
            return textComp.getText(range.getFrom(), range.length());
        } catch (BadLocationException ex) {
            ex.printStackTrace();;
        }
        return "";
    }

}

There are a number of other concepts you could use, like determining the range of the selection, which I've not shown, but which are mentioned in the links

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Wow , definitely difrent from what i excpected from the comment below but still impressive , but when it comes to
    and
    it will underline them too , not like it gonna happen to my app but just to know how to make it recognize it as it's an html white-spaces too?
    – a lovely person Feb 14 '19 at 02:20
  • I didn't have any issues with `
    ` or `
    `, but I did notice if I clicked on the white space it would underline the preceding and following word, neat. `getRangeOfWordUnderMouse` is basically testing the character which was clicked, you should be able to extract the attributes as well from the document
    – MadProgrammer Feb 14 '19 at 02:29
  • just for refrence , worked with `````` thank god it's not deprecated here. – a lovely person Feb 14 '19 at 02:51