Làm cách nào để thêm siêu liên kết trong JLabel?


Câu trả lời:


97

Bạn có thể làm điều này bằng cách sử dụng a JLabel, nhưng một cách thay thế sẽ là tạo kiểu a JButton. Bằng cách đó, bạn không phải lo lắng về khả năng truy cập và chỉ có thể kích hoạt các sự kiện bằng cách sử dụng 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 Luân phiên sử dụng một JTextFieldnhư được hiển thị trong câu trả lời này .
Andrew Thompson,

1
Ngay cả văn bản không phải là một phần của liên kết cũng có thể được nhấp để theo liên kết.
neuralmer

28

Tôi muốn đưa ra một giải pháp khác. Nó tương tự như những cái đã được đề xuất vì nó sử dụng mã HTML trong JLabel và đăng ký MouseListener trên đó, nhưng nó cũng hiển thị HandCursor khi bạn di chuyển chuột qua liên kết, vì vậy giao diện giống như những gì hầu hết người dùng mong đợi . Nếu tính năng duyệt không được nền tảng hỗ trợ, thì sẽ không tạo liên kết HTML có gạch chân màu xanh lam có thể gây hiểu lầm cho người dùng. Thay vào đó, liên kết chỉ được trình bày dưới dạng văn bản thuần túy. Điều này có thể được kết hợp với lớp SwingLink do @ dimo414 đề xuất.

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
không thực hiện kết nối trên EDT là một bắt tuyệt vời! Cần phải sửa chữa SwingX HyperlinkAction để không làm việc đó cũng :-)
Kleopatra

nộp một vấn đề trong SwingX: java.net/jira/browse/SWINGX-1530 - cảm ơn cho nuôi này :-)
Kleopatra

@kleopatra Bạn được chào đón :) Có vẻ như bạn không thể tái tạo hành vi chặn của Desktop.browse - trên máy chậm của tôi, nó chắc chắn chặn, đáng chú ý nhất là nếu trình duyệt chưa mở.
Stefan

điểm tốt! đã thêm nhận xét của bạn vào vấn đề - gần như có xu hướng đóng lại vì sẽ không khắc phục được, nhận xét của bạn đã lưu cho tôi :-)
kleopatra

Đây là một giải pháp thú vị. Tôi thích cách nó mở rộng JLabel - điều này có nghĩa là GroupLayout có nhiều khả năng định vị nó giống như một nhãn chứ không phải như một nút. Tôi nhận thấy rằng việc sử dụng các nút dường như làm tăng khoảng cách mà bạn nhận được giữa các thành phần ...
Trejkaz

17

Tôi đã viết một bài báo về cách đặt một siêu liên kết hoặc một mailto trên jLabel.

Vì vậy, chỉ cần thử :

Tôi nghĩ đó chính xác là những gì bạn đang tìm kiếm.

Đây là ví dụ về mã hoàn chỉnh:

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

Cập nhật Tôi đã thu dọn SwingLinklớp hơn nữa và thêm nhiều tính năng hơn; bản sao cập nhật của nó có thể được tìm thấy tại đây: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.java


Câu trả lời của @ McDowell rất hay, nhưng có một số thứ có thể được cải thiện. Đáng chú ý là văn bản khác với siêu liên kết có thể nhấp được và nó vẫn trông giống như một nút mặc dù một số kiểu đã được thay đổi / ẩn. Mặc dù khả năng truy cập là quan trọng, nhưng giao diện người dùng nhất quán cũng vậy.

Vì vậy, tôi đã tập hợp một lớp mở rộng JLabel dựa trên mã của McDowell. Nó khép kín, xử lý lỗi đúng cách và giống như một liên kết hơn:

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

Ví dụ, bạn cũng có thể thay đổi màu liên kết thành màu tím sau khi được nhấp vào, nếu điều đó có vẻ hữu ích. Tất cả đều khép kín, bạn chỉ cần gọi:

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

1
Tôi chỉ cần thêm yêu cầu kéo mới để thêm uri setter
boly38

Nếu con chuột trở thành một bàn tay, nó sẽ thậm chí còn tốt hơn!
Leon

@Leon hãy xem phiên bản được liên kết ở đầu câu trả lời của tôi, nó sử dụng setCursor(new Cursor(Cursor.HAND_CURSOR));và có một số cải tiến khác so với biến thể nội dòng trong câu trả lời này.
dimo414


13

Bạn có thể thử sử dụng JEditorPane thay vì JLabel. Điều này hiểu HTML cơ bản và sẽ gửi một sự kiện HyperlinkEvent tới HyperlinkListener mà bạn đăng ký với JEditPane.


1
Đây là giải pháp tốt nhất nếu bạn có văn bản với một số siêu liên kết trong đó (có thể được thay đổi nhanh chóng). Hầu hết các giải pháp khác yêu cầu đặt siêu kết nối trong một điều khiển riêng biệt.
user149408

5

Nếu <a href="link"> không hoạt động, thì:

  1. Tạo JLabel và thêm MouseListener (trang trí nhãn để trông giống như một siêu liên kết)
  2. Triển khai mouseClicked () sự kiện
  3. Trong quá trình triển khai sự kiện mouseClicked (), hãy thực hiện hành động của bạn

Hãy xem API java.awt.Desktop để mở liên kết bằng trình duyệt mặc định (API này chỉ có sẵn từ Java6).


4

Tôi biết mình hơi muộn đến bữa tiệc nhưng tôi đã thực hiện một phương pháp nhỏ mà người khác có thể thấy hay / hữu ích.

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

Nó sẽ cung cấp cho bạn một JLabel hoạt động giống như một liên kết thích hợp.

Trong hành động:

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

Nếu bạn không muốn có chú giải công cụ, chỉ cần gửi giá trị rỗng.

Hy vọng ai đó thấy điều này hữu ích! (Nếu bạn làm vậy, hãy cho tôi biết, tôi rất vui được nghe.)




1

Mã sau yêu cầu JHyperLinkđược thêm vào đường dẫn xây dựng của bạn.

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

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

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

Lưu ý rằng bạn có thể lấp đầy JComponentmảng với nhiều Swingthành phần hơn .

Kết quả:


0

Bạn có thể sử dụng điều này trong một

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

hoặc nếu bạn muốn sử dụng Internet Explorer hoặc Firefox, hãy thay thế chromebằng iexplorehoặcfirefox

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.