Search code examples
javaswingurljtextpane

Clickable text in a JTextPane


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?


Solution

  • 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();
            }
        }