Bagaimana cara menambahkan hyperlink di JLabel?

Jawaban:

97

Anda dapat melakukan ini dengan menggunakan a JLabel, tetapi alternatifnya adalah membuat gaya a JButton. Dengan begitu, Anda tidak perlu khawatir tentang aksesibilitas dan cukup mengaktifkan peristiwa menggunakan 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
sumber
2
+1 Bergantian gunakan a JTextFieldseperti yang ditunjukkan dalam jawaban ini .
Andrew Thompson
1
Bahkan teks yang bukan bagian dari link dapat diklik untuk mengikuti link tersebut.
neuralmer
28

Saya ingin menawarkan solusi lain. Ini mirip dengan yang sudah diusulkan karena menggunakan kode HTML dalam JLabel, dan mendaftarkan MouseListener di atasnya, tetapi juga menampilkan HandCursor saat Anda menggerakkan mouse ke atas tautan, sehingga tampilan & nuansanya persis seperti yang diharapkan sebagian besar pengguna . Jika penjelajahan tidak didukung oleh platform, tidak ada tautan HTML bergaris bawah biru yang dibuat yang dapat menyesatkan pengguna. Alih-alih, tautan hanya disajikan sebagai teks biasa. Ini dapat dikombinasikan dengan kelas SwingLink yang diusulkan oleh @ 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
sumber
1
tidak melakukan koneksi di EDT adalah pilihan yang bagus! Perlu memperbaiki SwingX HyperlinkAction agar tidak melakukannya juga :-)
kleopatra
mengajukan masalah di SwingX: java.net/jira/browse/SWINGX-1530 - terima kasih telah mengungkit hal ini :-)
kleopatra
@kleopatra Sama-sama :) Sepertinya Anda tidak dapat mereproduksi perilaku pemblokiran Desktop.browse - di komputer saya yang lambat, ini pasti memblokir, terutama jika browser belum terbuka.
Stefan
poin yang bagus! menambahkan komentar Anda ke masalah ini - hampir cenderung ditutup karena tidak dapat diperbaiki, komentar Anda menyelamatkan saya :-)
kleopatra
Ini adalah solusi yang menarik. Saya suka cara memperluas JLabel - ini berarti GroupLayout lebih cenderung memposisikannya seperti label, bukan seperti tombol. Saya perhatikan bahwa menggunakan tombol tampaknya meningkatkan jarak yang Anda dapatkan antar komponen ...
Trejkaz
17

Saya menulis artikel tentang cara menyetel hyperlink atau mailto ke jLabel.

Jadi coba saja :

Saya pikir itulah yang Anda cari.

Berikut contoh kode lengkapnya:

/**
 * 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
sumber
15

Perbarui Saya telah merapikan SwingLinkkelas lebih lanjut dan menambahkan lebih banyak fitur; salinan mutakhirnya dapat ditemukan di sini: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.java


Jawaban @ McDowell bagus, tetapi ada beberapa hal yang dapat diperbaiki. Khususnya teks selain hyperlink dapat diklik dan masih terlihat seperti tombol meskipun beberapa gaya telah diubah / disembunyikan. Meskipun aksesibilitas itu penting, UI yang koheren juga penting.

Jadi saya menyusun kelas yang memperluas JLabel berdasarkan kode McDowell. Itu mandiri, menangani kesalahan dengan benar, dan terasa lebih seperti tautan:

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

Anda juga dapat, misalnya, mengubah warna tautan menjadi ungu setelah diklik, jika itu tampak berguna. Semuanya serba lengkap, Anda cukup menelepon:

SwingLink link = new SwingLink("Java", "http://java.sun.com");
mainPanel.add(link);
dimo414
sumber
1
Saya baru saja menambahkan permintaan tarik baru untuk menambahkan penyetel uri
boly38
Jika mouse menjadi tangan, itu akan menjadi lebih baik!
Leon
@Leon lihat versi yang ditautkan di bagian atas jawaban saya, ini menggunakan setCursor(new Cursor(Cursor.HAND_CURSOR));dan memiliki beberapa peningkatan lain atas varian sebaris dalam jawaban ini.
dimo414
13

Anda dapat mencoba menggunakan JEditorPane sebagai ganti JLabel. Ini memahami HTML dasar dan akan mengirim acara HyperlinkEvent ke HyperlinkListener yang Anda daftarkan dengan JEditPane.

Edward Falk
sumber
1
Ini adalah solusi terbaik jika Anda memiliki teks dengan beberapa hyperlink di dalamnya (mungkin diubah saat itu juga). Sebagian besar solusi lain memerlukan penempatan hyperlink dalam kontrol terpisah.
pengguna149408
5

Jika <a href="link"> tidak berfungsi, maka:

  1. Buat JLabel dan tambahkan MouseListener (hiasi label agar terlihat seperti hyperlink)
  2. Implementasikan acara mouseClicked ()
  3. Dalam implementasi acara mouseClicked (), lakukan tindakan Anda

Lihat java.awt.Desktop API untuk membuka tautan menggunakan browser default (API ini hanya tersedia dari Java6).

Srikanth
sumber
4

Saya tahu saya agak terlambat ke pesta, tetapi saya membuat sedikit metode yang mungkin dianggap keren / berguna bagi orang lain.

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

Ini akan memberi Anda JLabel yang berfungsi seperti tautan yang tepat.

Beraksi:

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

Jika Anda tidak ingin tooltip kirim saja null.

Semoga seseorang menemukan ini berguna! (Jika ya, beri tahu saya, saya akan senang mendengarnya.)

Sutra Meshulam
sumber
4

Gunakan JEditorPanedengan a HyperlinkListener.

Elist
sumber
1

Sederhananya window.open(website url), ini bekerja setiap saat.

ini palsu
sumber
1

Kode berikut perlu JHyperLinkditambahkan ke jalur build Anda.

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

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

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

Perhatikan bahwa Anda dapat mengisi JComponentarray dengan lebih banyak Swingkomponen.

Hasil:

BullyWiiPlaza
sumber
0

Anda dapat menggunakan ini di bawah

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

atau jika Anda ingin menggunakan Internet Explorer atau Firefox ganti chromedengan iexploreataufirefox

Ionutz Asaftei
sumber