Comment ajouter un lien hypertexte dans JLabel?

Réponses:

97

Vous pouvez le faire en utilisant a JLabel, mais une alternative serait de styliser a JButton. De cette façon, vous n'avez pas à vous soucier de l' accessibilité et pouvez simplement déclencher des événements à l'aide d'un 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
la source
2
+1 Vous pouvez également utiliser a JTextFieldcomme indiqué dans cette réponse .
Andrew Thompson
1
Même le texte qui ne fait pas partie du lien peut être cliqué pour suivre le lien.
neuralmer
28

Je voudrais proposer encore une autre solution. Il est similaire à ceux déjà proposés car il utilise du code HTML dans un JLabel et enregistre un MouseListener dessus, mais il affiche également un HandCursor lorsque vous déplacez la souris sur le lien, de sorte que l'apparence est exactement ce que la plupart des utilisateurs attendent. . Si la navigation n'est pas prise en charge par la plate-forme, aucun lien HTML bleu souligné n'est créé qui pourrait induire l'utilisateur en erreur. Au lieu de cela, le lien est simplement présenté sous forme de texte brut. Cela pourrait être combiné avec la classe SwingLink proposée par @ 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
la source
1
ne pas faire le branchement sur l'EDT est une excellente prise! Besoin de corriger SwingX HyperlinkAction pour ne pas le faire aussi :-)
kleopatra
a déposé un problème dans SwingX: java.net/jira/browse/SWINGX-1530 - merci d'avoir soulevé ceci :-)
kleopatra
@kleopatra Vous êtes les bienvenus :) Il semble que vous ne puissiez pas reproduire le comportement de blocage de Desktop.browse - sur ma machine lente, il bloque à coup sûr, surtout si le navigateur n'est pas encore ouvert.
Stefan
bon point! a ajouté votre commentaire au problème - a presque tendance à se fermer car ne résout pas, votre commentaire m'a sauvé :-)
kleopatra
C'est une solution intéressante. J'aime la façon dont il étend JLabel - cela signifie que GroupLayout est plus susceptible de le positionner comme une étiquette, pas comme un bouton. J'ai remarqué que l'utilisation des boutons semble augmenter l'espacement entre les composants ...
Trejkaz
17

J'ai écrit un article sur la façon de définir un lien hypertexte ou un mailto sur un jLabel.

Alors essayez- le :

Je pense que c'est exactement ce que vous recherchez.

Voici l'exemple de code complet:

/**
 * 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
la source
15

Mise à jour J'ai rangé SwingLinkdavantage la classe et ajouté plus de fonctionnalités; une copie à jour de celui-ci peut être trouvée ici: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.java


La réponse de @ McDowell est excellente, mais il y a plusieurs choses qui pourraient être améliorées. Notamment, le texte autre que le lien hypertexte est cliquable et il ressemble toujours à un bouton même si une partie du style a été modifiée / masquée. Bien que l'accessibilité soit importante, une interface utilisateur cohérente l'est également.

J'ai donc mis en place une classe étendant JLabel basée sur le code de McDowell. Il est autonome, gère correctement les erreurs et ressemble plus à un lien:

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

Vous pouvez également, par exemple, changer la couleur du lien en violet après avoir cliqué dessus, si cela vous semble utile. Tout est autonome, vous appelez simplement:

SwingLink link = new SwingLink("Java", "http://java.sun.com");
mainPanel.add(link);
dimo414
la source
1
Je viens d'ajouter une nouvelle demande de tirage pour ajouter uri setter
boly38
Si la souris devient une main, ce sera encore mieux!
Leon
@Leon jetez un oeil à la version liée en haut de ma réponse, elle utilise setCursor(new Cursor(Cursor.HAND_CURSOR));et a quelques autres améliorations par rapport à la variante en ligne dans cette réponse.
dimo414
13

Vous pouvez essayer d'utiliser un JEditorPane au lieu d'un JLabel. Cela comprend le HTML de base et enverra un événement HyperlinkEvent au HyperlinkListener que vous enregistrez auprès de JEditPane.

Edward Falk
la source
1
C'est la meilleure solution si vous avez du texte contenant des hyperliens (éventuellement modifiés à la volée). La plupart des autres solutions nécessitent de placer le lien hypertexte dans un contrôle séparé.
user149408
5

Si <a href="link"> ne fonctionne pas, alors:

  1. Créez un JLabel et ajoutez un MouseListener (décorez l'étiquette pour qu'elle ressemble à un lien hypertexte)
  2. Mettre en œuvre mouseClicked () événement
  3. Dans l'implémentation de l'événement mouseClicked (), effectuez votre action

Jetez un œil à l' API java.awt.Desktop pour ouvrir un lien à l'aide du navigateur par défaut (cette API n'est disponible qu'à partir de Java6).

Srikanth
la source
4

Je sais que je suis un peu en retard à la fête mais j'ai fait une petite méthode que d'autres pourraient trouver cool / utile.

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;
}

Cela vous donnera un JLabel qui agit comme un lien approprié.

En action:

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

Si vous ne souhaitez aucune info-bulle, envoyez simplement un null.

J'espère que quelqu'un trouvera cela utile! (Si vous le faites, assurez-vous de me le faire savoir, je serais heureux de l'entendre.)

Soie Meshulam
la source
4

Utilisez a JEditorPaneavec a HyperlinkListener.

Elist
la source
1

Autrement dit window.open(website url), cela fonctionne à chaque fois.

c'est faux
la source
1

Le code suivant doit JHyperLinkêtre ajouté à votre chemin de génération.

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

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

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

Notez que vous pouvez remplir le JComponenttableau avec plus de Swingcomposants.

Résultat:

BullyWiiPlaza
la source
0

Vous pouvez l'utiliser sous un

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

ou si vous souhaitez utiliser Internet Explorer ou Firefox, remplacez chromepar iexploreoufirefox

Ionutz Asaftei
la source