Clickable text in a JTextPane

Joe picture Joe · Apr 21, 2013 · Viewed 7.4k times · Source

I have a JTextPane declared like the following:

JTextPane box = new JTextPane();
JScrollPane scroll = new JScrollPane();
StyledDocument doc = box.getStyledDocument();
scroll.setViewportView(box);
scroll = new JScrollPane(box);

And I am appending text to it as follows:

public void appendChatText(String text)
{   
    try
    {
        doc.insertString(doc.getLength(), text, null);
        box.setAutoscrolls(true);
        box.setCaretPosition(box.getDocument().getLength());    
    }
    catch(BadLocationException e)
    {
        e.printStackTrace();
    }
}

I also managed to easily get the JTextPane to display images and components as necessary, but I can't figure out how to code clickable text into a JTextPane. For example, I want it to print a message that says something like, "File uploaded to server. Accept *Decline*" and if the user clicks on the accept or decline strings then it executes the appropriate function. Any ideas on how this could be effectively achieved?

Answer

Joe picture Joe · Apr 23, 2013

I ended up solving this with a MouseListener and a class extending AsbstractAction. I added the text I wanted to be a clickable link to the JTextPane as follows:

`Style regularBlue = doc.addStyle("regularBlue", StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE));
 StyleConstants.setForeground(regularBlue, Color.BLUE);
 StyleConstants.setUnderline(regularBlue, true);
 regularBlue.addAttribute("linkact", new ChatLinkListener(textLink));
 doc.insertString(doc.getLength(), textLink, regularBlue);`

I initialised the MouseListener on the JTextPane elsewhere and added the following code to my listener class:

public void mouseClicked(MouseEvent e)
        {
            Element ele = doc.getCharacterElement(chatbox.viewToModel(e.getPoint()));
            AttributeSet as = ele.getAttributes();
            ChatLinkListener fla = (ChatLinkListener)as.getAttribute("linkact");
            if(fla != null)
            {
                fla.execute();
            }
        }

And finally, this referenced the class that actually performs the action:

class ChatLinkListener extends AbstractAction
    {
        private String textLink;

        ChatLinkListener(String textLink)
        {
            this.textLink = textLink;
        }

        protected void execute()
        {
            if("accept".equals(url))
            {
                //execute code
            }
            else if("decline".equals(url))
            {
                //execute code
            }
        }

        public void actionPerformed(ActionEvent e)
        {
            execute();
        }
    }