Como adicionar hiperlink no JLabel?

Respostas:

97

Você pode fazer isso usando a JLabel, mas uma alternativa seria estilizar a JButton. Dessa forma, você não precisa se preocupar com a acessibilidade e pode apenas disparar eventos usando um ActionListener.

  public static void main(String[] args) throws URISyntaxException {
    final URI uri = new URI("http://java.sun.com");
    class OpenUrlAction implements ActionListener {
      @Override public void actionPerformed(ActionEvent e) {
        open(uri);
      }
    }
    JFrame frame = new JFrame("Links");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(100, 400);
    Container container = frame.getContentPane();
    container.setLayout(new GridBagLayout());
    JButton button = new JButton();
    button.setText("<HTML>Click the <FONT color=\"#000099\"><U>link</U></FONT>"
        + " to go to the Java website.</HTML>");
    button.setHorizontalAlignment(SwingConstants.LEFT);
    button.setBorderPainted(false);
    button.setOpaque(false);
    button.setBackground(Color.WHITE);
    button.setToolTipText(uri.toString());
    button.addActionListener(new OpenUrlAction());
    container.add(button);
    frame.setVisible(true);
  }

  private static void open(URI uri) {
    if (Desktop.isDesktopSupported()) {
      try {
        Desktop.getDesktop().browse(uri);
      } catch (IOException e) { /* TODO: error handling */ }
    } else { /* TODO: error handling */ }
  }
McDowell
fonte
2
+1 Como alternativa, use a JTextFieldconforme mostrado nesta resposta .
Andrew Thompson
1
Mesmo o texto que não faz parte do link pode ser clicado para seguir o link.
neuralmer
28

Eu gostaria de oferecer mais uma solução. É semelhante aos já propostos, pois usa código HTML em um JLabel e registra um MouseListener nele, mas também exibe um HandCursor quando você move o mouse sobre o link, de modo que a aparência é exatamente como a maioria dos usuários esperaria . Se a navegação não for suportada pela plataforma, nenhum link HTML sublinhado em azul é criado, o que pode enganar o usuário. Em vez disso, o link é apresentado apenas como texto simples. Isso pode ser combinado com a classe SwingLink proposta por @ dimo414.

public class JLabelLink extends JFrame {

private static final String LABEL_TEXT = "For further information visit:";
private static final String A_VALID_LINK = "http://stackoverflow.com";
private static final String A_HREF = "<a href=\"";
private static final String HREF_CLOSED = "\">";
private static final String HREF_END = "</a>";
private static final String HTML = "<html>";
private static final String HTML_END = "</html>";

public JLabelLink() {
    setTitle("HTML link via a JLabel");
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    Container contentPane = getContentPane();
    contentPane.setLayout(new FlowLayout(FlowLayout.LEFT));

    JLabel label = new JLabel(LABEL_TEXT);
    contentPane.add(label);

    label = new JLabel(A_VALID_LINK);
    contentPane.add(label);
    if (isBrowsingSupported()) {
        makeLinkable(label, new LinkMouseListener());
    }

    pack();
}

private static void makeLinkable(JLabel c, MouseListener ml) {
    assert ml != null;
    c.setText(htmlIfy(linkIfy(c.getText())));
    c.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
    c.addMouseListener(ml);
}

private static boolean isBrowsingSupported() {
    if (!Desktop.isDesktopSupported()) {
        return false;
    }
    boolean result = false;
    Desktop desktop = java.awt.Desktop.getDesktop();
    if (desktop.isSupported(Desktop.Action.BROWSE)) {
        result = true;
    }
    return result;

}

private static class LinkMouseListener extends MouseAdapter {

    @Override
    public void mouseClicked(java.awt.event.MouseEvent evt) {
        JLabel l = (JLabel) evt.getSource();
        try {
            URI uri = new java.net.URI(JLabelLink.getPlainLink(l.getText()));
            (new LinkRunner(uri)).execute();
        } catch (URISyntaxException use) {
            throw new AssertionError(use + ": " + l.getText()); //NOI18N
        }
    }
}

private static class LinkRunner extends SwingWorker<Void, Void> {

    private final URI uri;

    private LinkRunner(URI u) {
        if (u == null) {
            throw new NullPointerException();
        }
        uri = u;
    }

    @Override
    protected Void doInBackground() throws Exception {
        Desktop desktop = java.awt.Desktop.getDesktop();
        desktop.browse(uri);
        return null;
    }

    @Override
    protected void done() {
        try {
            get();
        } catch (ExecutionException ee) {
            handleException(uri, ee);
        } catch (InterruptedException ie) {
            handleException(uri, ie);
        }
    }

    private static void handleException(URI u, Exception e) {
        JOptionPane.showMessageDialog(null, "Sorry, a problem occurred while trying to open this link in your system's standard browser.", "A problem occured", JOptionPane.ERROR_MESSAGE);
    }
}

private static String getPlainLink(String s) {
    return s.substring(s.indexOf(A_HREF) + A_HREF.length(), s.indexOf(HREF_CLOSED));
}

//WARNING
//This method requires that s is a plain string that requires
//no further escaping
private static String linkIfy(String s) {
    return A_HREF.concat(s).concat(HREF_CLOSED).concat(s).concat(HREF_END);
}

//WARNING
//This method requires that s is a plain string that requires
//no further escaping
private static String htmlIfy(String s) {
    return HTML.concat(s).concat(HTML_END);
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            new JLabelLink().setVisible(true);
        }
    });
}
}
Stefan
fonte
1
não fazer a conexão no EDT é uma excelente pegadinha! Precisa corrigir SwingX HyperlinkAction para não fazê-lo tão bem :-)
kleopatra
registrou um problema no SwingX: java.net/jira/browse/SWINGX-1530 - obrigado por trazer isso à tona :-)
kleopatra
@kleopatra De nada :) Parece que você não conseguiu reproduzir o comportamento de bloqueio do Desktop.browse - na minha máquina lenta ele bloqueia com certeza, principalmente se o navegador ainda não estiver aberto.
Stefan
bom ponto! adicionou seu comentário ao problema - quase tendeu a fechar porque não corrige, seu comentário me salvou :-)
kleopatra
Esta é uma solução interessante. Gosto de como ele estende o JLabel - isso significa que o GroupLayout provavelmente o posicionará como um rótulo, não como um botão. Percebi que o uso de botões parece aumentar o espaçamento que você obtém entre os componentes ...
Trejkaz
17

Escrevi um artigo sobre como definir um hiperlink ou mailto em um jLabel.

Então, basta tentar isso :

Acho que é exatamente isso que você está procurando.

Aqui está o exemplo de código completo:

/**
 * Example of a jLabel Hyperlink and a jLabel Mailto
 */

import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 *
 * @author ibrabelware
 */
public class JLabelLink extends JFrame {
    private JPanel pan;
    private JLabel contact;
        private JLabel website;
    /**
     * Creates new form JLabelLink
     */
    public JLabelLink() {
        this.setTitle("jLabelLinkExample");
        this.setSize(300, 100);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);

        pan = new JPanel();
        contact = new JLabel();
        website = new JLabel();

        contact.setText("<html> contact : <a href=\"\">[email protected]</a></html>");
        contact.setCursor(new Cursor(Cursor.HAND_CURSOR));

        website.setText("<html> Website : <a href=\"\">http://www.google.com/</a></html>");
        website.setCursor(new Cursor(Cursor.HAND_CURSOR));

    pan.add(contact);
    pan.add(website);
        this.setContentPane(pan);
        this.setVisible(true);
        sendMail(contact);
        goWebsite(website);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Create and display the form
         */
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new JLabelLink().setVisible(true);
            }
        });
    }

    private void goWebsite(JLabel website) {
        website.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                try {
                    Desktop.getDesktop().browse(new URI("http://www.google.com/webhp?nomo=1&hl=fr"));
                } catch (URISyntaxException | IOException ex) {
                    //It looks like there's a problem
                }
            }
        });
    }

    private void sendMail(JLabel contact) {
        contact.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                try {
                    Desktop.getDesktop().mail(new URI("mailto:[email protected]?subject=TEST"));
                } catch (URISyntaxException | IOException ex) {
                    //It looks like there's a problem
                }
            }
        });
    }
}
ibrabelware
fonte
15

Atualização Eu organizei ainda mais a SwingLinkclasse e adicionei mais recursos; uma cópia atualizada pode ser encontrada aqui: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.java


A resposta de @McDowell é ótima, mas há várias coisas que podem ser melhoradas. Notavelmente, o texto diferente do hiperlink é clicável e ainda parece um botão, embora parte do estilo tenha sido alterado / oculto. Embora a acessibilidade seja importante, uma IU coerente também é.

Então, eu montei uma classe que estende JLabel com base no código de McDowell. É independente, lida com erros de maneira adequada e parece mais um link:

public class SwingLink extends JLabel {
  private static final long serialVersionUID = 8273875024682878518L;
  private String text;
  private URI uri;

  public SwingLink(String text, URI uri){
    super();
    setup(text,uri);
  }

  public SwingLink(String text, String uri){
    super();
    setup(text,URI.create(uri));
  }

  public void setup(String t, URI u){
    text = t;
    uri = u;
    setText(text);
    setToolTipText(uri.toString());
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        open(uri);
      }
      public void mouseEntered(MouseEvent e) {
        setText(text,false);
      }
      public void mouseExited(MouseEvent e) {
        setText(text,true);
      }
    });
  }

  @Override
  public void setText(String text){
    setText(text,true);
  }

  public void setText(String text, boolean ul){
    String link = ul ? "<u>"+text+"</u>" : text;
    super.setText("<html><span style=\"color: #000099;\">"+
    link+"</span></html>");
    this.text = text;
  }

  public String getRawText(){
    return text;
  }

  private static void open(URI uri) {
    if (Desktop.isDesktopSupported()) {
      Desktop desktop = Desktop.getDesktop();
      try {
        desktop.browse(uri);
      } catch (IOException e) {
        JOptionPane.showMessageDialog(null,
            "Failed to launch the link, your computer is likely misconfigured.",
            "Cannot Launch Link",JOptionPane.WARNING_MESSAGE);
      }
    } else {
      JOptionPane.showMessageDialog(null,
          "Java is not able to launch links on your computer.",
          "Cannot Launch Link", JOptionPane.WARNING_MESSAGE);
    }
  }
}

Você também pode, por exemplo, alterar a cor do link para roxo depois de ser clicado, se isso parecer útil. É tudo independente, você simplesmente chama:

SwingLink link = new SwingLink("Java", "http://java.sun.com");
mainPanel.add(link);
dimo414
fonte
1
Acabei de adicionar uma nova solicitação de pull para adicionar uri setter
boly38
Se o mouse virar mão, será ainda melhor!
Leon
@Leon dê uma olhada na versão vinculada no topo da minha resposta, ela usa setCursor(new Cursor(Cursor.HAND_CURSOR));e tem algumas outras melhorias em relação à variante inline nesta resposta.
dimo414
13

Você pode tentar usar um JEditorPane em vez de um JLabel. Isso entende HTML básico e enviará um evento HyperlinkEvent para o HyperlinkListener que você registrar no JEditPane.

Edward Falk
fonte
1
Esta é a melhor solução se você tiver texto com alguns hiperlinks (possivelmente alterados rapidamente). A maioria das outras soluções exige a colocação do hiperlink em um controle separado.
user149408
5

Se <a href="link"> não funcionar, então:

  1. Crie um JLabel e adicione um MouseListener (decore o rótulo para se parecer com um hiperlink)
  2. Implementar evento mouseClicked ()
  3. Na implementação do evento mouseClicked (), execute sua ação

Dê uma olhada na API java.awt.Desktop para abrir um link usando o navegador padrão (esta API está disponível apenas no Java6).

Srikanth
fonte
4

Sei que estou meio atrasado para a festa, mas criei um pequeno método que outros podem achar legal / útil.

public static JLabel linkify(final String text, String URL, String toolTip)
{
    URI temp = null;
    try
    {
        temp = new URI(URL);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    final URI uri = temp;
    final JLabel link = new JLabel();
    link.setText("<HTML><FONT color=\"#000099\">"+text+"</FONT></HTML>");
    if(!toolTip.equals(""))
        link.setToolTipText(toolTip);
    link.setCursor(new Cursor(Cursor.HAND_CURSOR));
    link.addMouseListener(new MouseListener()
    {
        public void mouseExited(MouseEvent arg0)
        {
            link.setText("<HTML><FONT color=\"#000099\">"+text+"</FONT></HTML>");
        }

        public void mouseEntered(MouseEvent arg0)
        {
            link.setText("<HTML><FONT color=\"#000099\"><U>"+text+"</U></FONT></HTML>");
        }

        public void mouseClicked(MouseEvent arg0)
        {
            if (Desktop.isDesktopSupported())
            {
                try
                {
                    Desktop.getDesktop().browse(uri);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
            else
            {
                JOptionPane pane = new JOptionPane("Could not open link.");
                JDialog dialog = pane.createDialog(new JFrame(), "");
                dialog.setVisible(true);
            }
        }

        public void mousePressed(MouseEvent e)
        {
        }

        public void mouseReleased(MouseEvent e)
        {
        }
    });
    return link;
}

Isso lhe dará um JLabel que atua como um link adequado.

Em ação:

public static void main(String[] args)
{
    JFrame frame = new JFrame("Linkify Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 100);
    frame.setLocationRelativeTo(null);
    Container container = frame.getContentPane();
    container.setLayout(new GridBagLayout());
    container.add(new JLabel("Click "));
    container.add(linkify("this", "http://facebook.com", "Facebook"));
    container.add(new JLabel(" link to open Facebook."));
    frame.setVisible(true);
}

Se você não quiser nenhuma dica, envie um nulo.

Espero que alguém ache isso útil! (Se o fizer, não se esqueça de me avisar, terei todo o gosto em saber.)

Meshulam Silk
fonte
4

Use um JEditorPanecom um HyperlinkListener.

Elist
fonte
1

Basta colocar window.open(website url), funciona sempre.

isto é falso
fonte
1

O código a seguir precisa JHyperLinkser adicionado ao seu caminho de construção.

JHyperlink stackOverflow = new JHyperlink("Click HERE!",
                "https://www.stackoverflow.com/");

JComponent[] messageComponents = new JComponent[] { stackOverflow };

JOptionPane.showMessageDialog(null, messageComponents, "StackOverflow",
                JOptionPane.PLAIN_MESSAGE);

Observe que você pode preencher a JComponentmatriz com mais Swingcomponentes.

Resultado:

BullyWiiPlaza
fonte
0

Você pode usar isso em um

actionListener ->  Runtime.getRuntime().exec("cmd.exe /c start chrome www.google.com")`

ou se você quiser usar o Internet Explorer ou o Firefox, substitua chromepor iexploreoufirefox

Ionutz Asaftei
fonte