31

I'm using a JOptionPane to display some product information and need to add some links to web pages.

I've figured out that you can use a JLabel containing html, so I have included an <a href> link. The link shows up blue and underlined in the dialog, however it is not clickable.

For example, this should also work:

public static void main(String[] args) throws Throwable
{
    JOptionPane.showMessageDialog(null, "<html><a href=\"http://google.com/\">a link</a></html>");
}

How do I get clickable links within a JOptionPane?

Thanks, Paul.

EDIT - eg solution

public static void main(String[] args) throws Throwable
{
    // for copying style
    JLabel label = new JLabel();
    Font font = label.getFont();

    // create some css from the label's font
    StringBuffer style = new StringBuffer("font-family:" + font.getFamily() + ";");
    style.append("font-weight:" + (font.isBold() ? "bold" : "normal") + ";");
    style.append("font-size:" + font.getSize() + "pt;");

    // html content
    JEditorPane ep = new JEditorPane("text/html", "<html><body style=\"" + style + "\">" //
            + "some text, and <a href=\"http://google.com/\">a link</a>" //
            + "</body></html>");

    // handle link events
    ep.addHyperlinkListener(new HyperlinkListener()
    {
        @Override
        public void hyperlinkUpdate(HyperlinkEvent e)
        {
            if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED))
                Desktop.getDesktop().browse(e.getURL().toString()); // roll your own link launcher or use Desktop if J6+
        }
    });
    ep.setEditable(false);
    ep.setBackground(label.getBackground());

    // show
    JOptionPane.showMessageDialog(null, ep);
}
pstanton
  • 35,033
  • 24
  • 126
  • 168
  • 6
    at the solution posted I can't find the class ProcessHandler . Where does it come from? – alexandre1985 Mar 12 '15 at 22:31
  • 2
    Instead of ProcessHandler, you can use `Desktop.getDesktop().browse(e.getURL().toURI())` – Joshua Goldberg Jan 28 '19 at 23:06
  • Using non-existent `ProcessHandler.launchUrl()` and still considering it as a solution is wrong - downvoted... @JoshuaGoldberg solution works as it should (OP should edit its "solution" to be universal, not just a statement "Use Desktop instead...") – qraqatit Sep 16 '21 at 11:41

2 Answers2

18

You can add any component to a JOptionPane.

So add a JEditorPane which displays your HTML and supports a HyperlinkListener.

camickr
  • 321,443
  • 19
  • 166
  • 288
7

The solution proposed below the answer does not work with Nimbus Look and Feel. Nimbus overrides the background color and makes the background white. The solution is to set the background color in the css. You also need to remove the component border. Here is a class that implements a solution that works with Nimbus (I Did not check other L&F):

import java.awt.Color;
import java.awt.Font;

import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;

public class MessageWithLink extends JEditorPane {
    private static final long serialVersionUID = 1L;

    public MessageWithLink(String htmlBody) {
        super("text/html", "<html><body style=\"" + getStyle() + "\">" + htmlBody + "</body></html>");
        addHyperlinkListener(new HyperlinkListener() {
            @Override
            public void hyperlinkUpdate(HyperlinkEvent e) {
                if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
                    // Process the click event on the link (for example with java.awt.Desktop.getDesktop().browse())
                    System.out.println(e.getURL()+" was clicked");
                }
            }
        });
        setEditable(false);
        setBorder(null);
    }

    static StringBuffer getStyle() {
        // for copying style
        JLabel label = new JLabel();
        Font font = label.getFont();
        Color color = label.getBackground();

        // create some css from the label's font
        StringBuffer style = new StringBuffer("font-family:" + font.getFamily() + ";");
        style.append("font-weight:" + (font.isBold() ? "bold" : "normal") + ";");
        style.append("font-size:" + font.getSize() + "pt;");
        style.append("background-color: rgb("+color.getRed()+","+color.getGreen()+","+color.getBlue()+");");
        return style;
    }
}

Usage:

JOptionPane.showMessageDialog(null, new MessageWithLink("Here is a link on <a href=\"http://www.google.com\">http://www.google.com</a>"));
Jean-Marc Astesana
  • 1,242
  • 3
  • 16
  • 24