0

My goal is to make anyGivenWord in a JTextArea "actionable". For example, when you hover the mouse over anyGivenWord, a tooltip appears, but not when you hover the mouse over any other word in the JTextArea. Since you can't do this directly to my knowledge, I was thinking of placing a component over where every anyGivenWord appears in the JTextArea, and have it re-position itself when the JTextArea's size changes, so that clicking on what appears to be anyGivenWord is actually clicking on the component(resulting in some listener being triggered). To do this, I would need to know at what point(x,y) that word occurs, so I can place the component at that point.

I was thinking I could search through the JTextArea and select instances of anyGivenWord, and then getSelectionStart() and getSelectionEnd(), but I think the int those methods return is the index of the first/last letter selected, as in, its position in the string returned by getText(). What I need is the x/y coordinates. Is this possible?

If not...any suggestions for more elegant ways to do what I'm trying to do?

A. L. Strine
  • 611
  • 1
  • 7
  • 23
  • Only been coding with Java for about 3 months, and only coding with any language just under a year - forgive my neophyte status XD – A. L. Strine Sep 01 '17 at 17:48

2 Answers2

1

You can use any JTextComponent and with a few methods (provided below) you can gather several different items from your text like:

  • The Character located under the current mouse pointer location;
  • The Word located under the current mouse pointer location;
  • The Selected Text located under the current mouse pointer location (if selected);
  • The Highlighted Text located under the current mouse pointer location (if you're into highlighting within the text as well);
  • Is the text under mouse pointer Selected?;
  • Is the text under mouse pointer Highlighted?.

As @camickr has already so generously pointed out, the key here is the use of the JTextComponent.viewToModel() method (I believe all Swing Text components contain this method) in order to acquire the text index location in relation to where the current mouse pointer is located within the component.

Here are some methods to play with:

/**
     * This method will return either boolean true or false if the text contained 
     * under the current mouse pointer location within a JTextComponent is Selected 
     * or not. If the text under the mouse is found to be Selected then boolean
     * true is returned. If the text under the mouse pointer is NOT found to be 
     * Selected then boolean false is returned.<br><br>
     * 
     * This method is not to be confused with the getHighlightedUnderMouse() method. 
     * Highlighted text and Selected text are two completely different things. 
     * Highlighted Text can be text which is Highlighted (generally with a specific 
     * color) and can be in many different locations throughout the entire document 
     * whereas Selected Text is generally done by dragging the mouse over a document 
     * location while holding the left mouse button making the text SELECTED.<br><br>
     * 
     * This method is generally run within a JTextComponent MouseMove Event but can be 
     * run from any JTextComponent Mouse event which will provide the current mouse 
     * coordinates within the supplied JTextComponent Object.
     * 
     * @param textComp (JTextComponent) The JTextComponent object to work on. This 
     * can be the component variable name for either a JTextField, JTextArea, 
     * JFormattedField, JPasswordField, JTextPane, and JEditorPane.<br>
     * 
     * @param textAreaMouseXLocation (Integer) The current X Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int x = evt.getX();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @param textAreaMouseYLocation (Integer) The current Y Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int y = evt.getY();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @return (Boolean) True if the text under the current mouse pointer location 
     * within the supplied JTextComponent is Selected and false if it is not.
     */
    public static boolean isSelectededUnderMouse(JTextComponent textComp, int textAreaMouseXLocation,
                                           int textAreaMouseYLocation) {
        boolean isSelected = false;
        if (textComp.getText().isEmpty()) { return false; }

        Point pt = new Point(textAreaMouseXLocation, textAreaMouseYLocation);
        int pos = textComp.viewToModel(pt);

        int start = textComp.getSelectionStart();
        int end = textComp.getSelectionEnd();
        if (pos >= start && pos <= end) {
            isSelected = true;
        }
        return isSelected;
    }

    /**
     * This method will return either boolean true or false if the text contained 
     * under the current mouse pointer location within a JTextComponent is Highlighted 
     * or not. If the text under the mouse is found to be Highlighted then boolean
     * true is returned. If the text under the mouse pointer is not found to be 
     * highlighted then boolean false is returned.<br><br>
     * 
     * This method is not to be confused with the getSelectedUnderMouse() method. 
     * Highlighted text and Selected text are two completely different things. 
     * Highlighted Text can be text which is Highlighted (generally with a specific 
     * color) and can be in many different locations throughout the entire document 
     * whereas Selected Text is generally done by dragging the mouse over a document 
     * location while holding the left mouse button making the text SELECTED.<br><br>
     * 
     * This method is generally run within a JTextComponent's MouseMove Event but can be 
     * run from any JTextComponent's Mouse event which will provide the current mouse 
     * coordinates within the supplied JTextArea Object.
     * 
     * @param textComp (JTextComponent) The JTextComponent object to work on. This 
     * can be the component variable name for either a JTextField, JTextArea, 
     * JFormattedField, JPasswordField, JTextPane, and JEditorPane.<br>
     * 
     * @param textAreaMouseXLocation (Integer) The current X Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int x = evt.getX();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @param textAreaMouseYLocation (Integer) The current Y Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int y = evt.getY();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @return (Boolean) True if the text under the current mouse pointer location 
     * within the supplied JTextComponent is Highlighted and false if it is not.
     */
    public static boolean isHighlightededUnderMouse(JTextComponent textComp, int textAreaMouseXLocation,
                                           int textAreaMouseYLocation) {
        boolean isHighlighted = false;
        if (textComp.getText().isEmpty()) { return false; }

        Point pt = new Point(textAreaMouseXLocation, textAreaMouseYLocation);
        int pos = textComp.viewToModel(pt);

        Highlighter.Highlight[] allHighlights = textComp.getHighlighter().getHighlights();
        String strg = "";
        for (int i = 0; i < allHighlights.length; i++) {
            int start =  (int)allHighlights[i].getStartOffset();
            int end =  (int)allHighlights[i].getEndOffset();
            if (pos >= start && pos <= end) {
                isHighlighted = true;
                break;
            }
        }        
        return isHighlighted;
    }

    /**
     * This method will return the "Selected" text contained under the mouse pointer
     * location within a JTextComonent.<br><br>
     * 
     * This method is not to be confused with the getHighlightedUnderMouse() method. 
     * Highlighted text and Selected text are two completely different things. 
     * Highlighted Text can be text which is Highlighted (generally with a specific 
     * color) and can be in many different locations throughout the entire document 
     * whereas Selected Text is generally done by dragging the mouse over a document 
     * location while holding the left mouse button making the text SELECTED.<br><br>
     * 
     * This method is generally run within a Text Component's MouseMove Event but can be 
     * run from any Text Component's Mouse event which will provide the current mouse 
     * coordinates within the supplied Text Component Object.
     * 
     * @param textComp (JTextComponent) The JTextComponent object to work on. This 
     * can be the component variable name for either a JTextField, JTextArea, 
     * JFormattedField, JPasswordField, JTextPane, and JEditorPane.<br>
     * 
     * @param textAreaMouseXLocation (Integer) The current X Location of the mouse 
     * pointer. This value can be acquired from the Text Component's MouseMove event like 
     * this <code>int x = evt.getX();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @param textAreaMouseYLocation (Integer) The current Y Location of the mouse 
     * pointer. This value can be acquired from the Text Component's MouseMove event like 
     * this <code>int y = evt.getY();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @return (String) The current selected string located under the current mouse 
     * location.
     */
    public static String getSelectededUnderMouse(JTextComponent textComp, int textAreaMouseXLocation,
                                           int textAreaMouseYLocation) {
        String selectedText = "";
        if (textComp.getText().isEmpty()) { return selectedText; }

        Point pt = new Point(textAreaMouseXLocation, textAreaMouseYLocation);
        int pos = textComp.viewToModel(pt);

        int start = textComp.getSelectionStart();
        int end = textComp.getSelectionEnd();
        int selectedLength = (end - start);
        if (pos >= start && pos <= end) {
            try {
                selectedText = textComp.getText(start, selectedLength);
            } 
            catch (BadLocationException ex) {
                // Ignore!!!
            }
        }
        return selectedText;
    }

    /**
     * This method will return the "Highlighted" text contained under the mouse pointer
     * location within a JTextComponent.<br><br>
     * 
     * This method is not to be confused with the getSelectedUnderMouse() method. 
     * Highlighted text and Selected text are two completely different things. 
     * Highlighted Text can be text which is Highlighted (generally with a specific 
     * color) and can be in many different locations throughout the entire document 
     * whereas Selected Text is generally done by dragging the mouse over a document 
     * location while holding the left mouse button making the text SELECTED.<br><br>
     * 
     * This method is generally run within a JTextComponent MouseMove Event but can be 
     * run from any JTextComponent Mouse event which will provide the current mouse 
     * coordinates within the supplied JTextComponent Object.
     * 
     * @param textComp (JTextComponent) The JTextComponent object to work on. This 
     * can be the component variable name for either a JTextField, JTextArea, 
     * JFormattedField, JPasswordField, JTextPane, and JEditorPane.<br>
     * 
     * @param textAreaMouseXLocation (Integer) The current X Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int x = evt.getX();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @param textAreaMouseYLocation (Integer) The current Y Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int y = evt.getY();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @return (String) The current highlighted string located under the current mouse 
     * location.
     */
    public static String getHighlightededUnderMouse(JTextComponent textComp, int textAreaMouseXLocation,
                                           int textAreaMouseYLocation) {
        if (textComp.getText().isEmpty()) { return ""; }

        Point pnt = new Point(textAreaMouseXLocation, textAreaMouseYLocation);
        int pos = textComp.viewToModel(pnt);

        String highlightedText = "";
        Highlighter.Highlight[] allHighlights = textComp.getHighlighter().getHighlights();
        if (allHighlights.length > 0) { 
            for (int i = 0; i < allHighlights.length; i++) {
                int start =  (int)allHighlights[i].getStartOffset();
                int end =  (int)allHighlights[i].getEndOffset();
                int hlStringLength = (end-start);
                if (pos >= start && pos <= end) {
                    try {
                        highlightedText = textComp.getText(start, hlStringLength);
                        break;
                    } 
                    catch (BadLocationException ex) { 
                        // Ignore!!!
                    }
                }

            }
        }
        return highlightedText;
    }

    /**
     * This method would normally be called within a JTextComponent's MouseMove Event.
     * 
     * @param textComp (JTextComponent) The JTextComponent object to work on. This 
     * can be the component variable name for either a JTextField, JTextArea, 
     * JFormattedField, JPasswordField, JTextPane, and JEditorPane.<br>
     * 
     * @param textAreaMouseXLocation (Integer) The current X Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int x = evt.getX();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @param textAreaMouseYLocation (Integer) The current Y Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int y = evt.getY();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @return (String) The current character located under the current mouse 
     * location.
     */
    public static String getCharUnderMouse(JTextComponent textComp, int textAreaMouseXLocation,
                                           int textAreaMouseYLocation) {
        String character = "";
        Point pt = new Point(textAreaMouseXLocation, textAreaMouseYLocation);
        int pos = textComp.viewToModel(pt);
        try {
            character = textComp.getDocument().getText(pos, 1);
        } 
        catch (BadLocationException ex) { 
            // Ignore!! 
        }
        return character;
    }

    /**
     * This method would normally be called within a JTextComponent's MouseMove Event.
     * 
     * @param textComp (JTextArea) The JTextComponent object to work on. This 
     * can be the component variable name for either a JTextField, JTextArea, 
     * JFormattedField, JPasswordField, JTextPane, and JEditorPane.<br>
     * 
     * @param textAreaMouseXLocation (Integer) The current X Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int x = evt.getX();</code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @param textAreaMouseYLocation (Integer) The current Y Location of the mouse 
     * pointer. This value can be acquired from the JTextComponent's MouseMove event like 
     * this <code>int y = evt.getY();<code> where evt is the <b>java.awt.event.MouseEvent</b> 
     * parameter variable.<br>
     * 
     * @return (String) The current Word located under the current mouse location.
     */
    public static String getWordUnderMouse(JTextComponent textComp, int textAreaMouseXLocation,
                                           int textAreaMouseYLocation) {
        Point pt = new Point(textAreaMouseXLocation, textAreaMouseYLocation);
        int pos = textComp.viewToModel(pt);
        String word = "";
        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);
            word = textComp.getText( begOffs, endOffs - begOffs );
        } 
        catch( BadLocationException ex ) {
            // Ignore this exception!!!
        }
        return word;
    }
DevilsHnd - 退職した
  • 8,739
  • 2
  • 19
  • 22
0

You can use a JEditorPane with HTML and add Hyperlinks to any given word. Read the section from the Swing tutorial on How to Use Editor Panes for the basics to get you started.

You can then add a HyperlinkListener to respond to events when the word is clicked. Read the JEditorPane API for an example of using a HyperlinkListener.

For example, when you hover the mouse over anyGivenWord, a tooltip appears,

If you don't want to use Hyperlinks then you could control the tooltip text by overriding the getToolTipText(...) method. This method receives the MouseEvent so you can get the mouse location. You can then use the viewToModel(...) method of the JTextArea to get the offset of the mouse into the Document. Then check out the Utilities. class which will help you get the start/end offsets of the word so you can use the getText(...) method to extract the word at the current mouse location.

camickr
  • 321,443
  • 19
  • 166
  • 288