Come aggiungere un collegamento ipertestuale in JLabel?


Risposte:


97

Puoi farlo usando a JLabel, ma un'alternativa sarebbe lo stile a JButton. In questo modo, non devi preoccuparti dell'accessibilità e puoi semplicemente attivare gli eventi utilizzando un file 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 */ }
  }

2
+1 In alternativa, usa un JTextFieldcome mostrato in questa risposta .
Andrew Thompson

1
Anche il testo che non fa parte del collegamento può essere cliccato per seguire il collegamento.
neuralmer

28

Vorrei offrire ancora un'altra soluzione. È simile a quelli già proposti in quanto utilizza il codice HTML in una JLabel e registra un MouseListener su di esso, ma mostra anche un HandCursor quando sposti il ​​mouse sul collegamento, quindi l'aspetto è proprio come quello che la maggior parte degli utenti si aspetterebbe . Se la navigazione non è supportata dalla piattaforma, non viene creato alcun collegamento HTML sottolineato in blu che potrebbe fuorviare l'utente. Invece, il collegamento viene presentato solo come testo normale. Questo potrebbe essere combinato con la classe SwingLink proposta da @ 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);
        }
    });
}
}

1
non fare il collegamento sull'EDT è un'ottima presa! È necessario correggere SwingX HyperlinkAction in modo che non lo faccia anche :-)
kleopatra

ha presentato un problema in SwingX: java.net/jira/browse/SWINGX-1530 - grazie per aver sollevato questo problema :-)
kleopatra

@kleopatra Sei il benvenuto :) Sembra che tu non possa riprodurre il comportamento di blocco di Desktop.browse - sulla mia macchina lenta si blocca di sicuro, in particolare se il browser non è ancora aperto.
Stefan

buon punto! ha aggiunto il tuo commento al problema - tendeva quasi a chiudersi perché non si risolverà, il tuo commento mi ha salvato :-)
kleopatra

Questa è una soluzione interessante. Mi piace come estende JLabel: questo significa che GroupLayout è più probabile che lo posizioni come un'etichetta, non come un pulsante. Ho notato che l'uso dei pulsanti sembra aumentare la spaziatura tra i componenti ...
Trejkaz

17

Ho scritto un articolo su come impostare un collegamento ipertestuale o un mailto su una jLabel.

Quindi basta provare che :

Penso che sia esattamente quello che stai cercando.

Ecco l'esempio di codice 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=\"\">YourEmailAddress@gmail.com</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:YourEmailAddress@gmail.com?subject=TEST"));
                } catch (URISyntaxException | IOException ex) {
                    //It looks like there's a problem
                }
            }
        });
    }
}

15

Aggiornamento Ho riordinato ulteriormente la SwingLinkclasse e aggiunto altre funzionalità; una copia aggiornata può essere trovata qui: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.java


La risposta di @ McDowell è ottima, ma ci sono molte cose che potrebbero essere migliorate. In particolare, il testo diverso dal collegamento ipertestuale è selezionabile e sembra ancora un pulsante anche se alcuni stili sono stati modificati / nascosti. Sebbene l'accessibilità sia importante, lo è anche un'interfaccia utente coerente.

Quindi ho messo insieme una classe che estende JLabel basata sul codice di McDowell. È autonomo, gestisce correttamente gli errori e sembra più un collegamento:

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

Potresti anche, ad esempio, cambiare il colore del collegamento in viola dopo aver fatto clic, se ti è sembrato utile. È tutto autonomo, chiami semplicemente:

SwingLink link = new SwingLink("Java", "http://java.sun.com");
mainPanel.add(link);

1
Ho appena aggiunto una nuova richiesta di pull per aggiungere uri setter
boly38

Se il mouse diventa una mano, sarà ancora meglio!
Leon

@Leon dai un'occhiata alla versione collegata nella parte superiore della mia risposta, utilizza setCursor(new Cursor(Cursor.HAND_CURSOR));e presenta alcuni altri miglioramenti rispetto alla variante in linea in questa risposta.
dimo414


13

Potresti provare a utilizzare JEditorPane invece di JLabel. Questo comprende l'HTML di base e invierà un evento HyperlinkEvent all'HyperlinkListener che registri con JEditPane.


1
Questa è la soluzione migliore se hai del testo con alcuni collegamenti ipertestuali (possibilmente modificati al volo). La maggior parte delle altre soluzioni richiedono l'inserimento del collegamento ipertestuale in un controllo separato.
user149408

5

Se <a href="link"> non funziona, allora:

  1. Crea una JLabel e aggiungi un MouseListener (decora l'etichetta in modo che assomigli a un collegamento ipertestuale)
  2. Implementa mouseClicked () evento
  3. Nell'implementazione dell'evento mouseClicked (), esegui la tua azione

Dai un'occhiata all'API java.awt.Desktop per aprire un collegamento utilizzando il browser predefinito (questa API è disponibile solo da Java6).


4

So di essere un po 'in ritardo per la festa, ma ho creato un piccolo metodo che altri potrebbero trovare interessante / 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;
}

Ti darà una JLabel che agisce come un collegamento appropriato.

In azione:

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 non desideri alcun suggerimento, invia semplicemente un null.

Spero che qualcuno lo trovi utile! (Se lo fai, assicurati di farmelo sapere, sarei felice di ascoltarlo.)


4

Usa a JEditorPanecon a HyperlinkListener.



1

Il codice seguente JHyperLinkdeve essere aggiunto al percorso di compilazione.

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

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

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

Nota che puoi riempire l' JComponentarray con più Swingcomponenti.

Risultato:


0

Puoi usarlo sotto un file

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

oppure, se desideri utilizzare Internet Explorer o Firefox, sostituisci chromecon iexploreofirefox

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.