如何在 JLabel 中添加超链接?

Posted

技术标签:

【中文标题】如何在 JLabel 中添加超链接?【英文标题】:How to add hyperlink in JLabel? 【发布时间】:2010-10-06 09:02:55 【问题描述】:

在 JLabel 中添加超链接的最佳方法是什么?我可以使用html标签获取视图,但是当用户点击它时如何打开浏览器?

【问题讨论】:

http://sourceforge.net/projects/jhyperlink/ 您可以在这里找到简单的解决方案:solution 【参考方案1】:

也许改用SwingX 中的JXHyperlink。它扩展了JButton。一些有用的链接:

Class JXHyperlink SwingX: Consider JXHyperlink As An Alternative To Buttons

【讨论】:

【参考方案2】:

更新 我进一步整理了SwingLink 类并添加了更多功能;可以在此处找到它的最新副本:https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.java


@McDowell 的回答很好,但有几件事可以改进。值得注意的是,超链接以外的文本是可点击的,即使某些样式已更改/隐藏,它仍然看起来像一个按钮。虽然可访问性很重要,但连贯的 UI 也很重要。

所以我根据 McDowell 的代码组合了一个扩展 JLabel 的类。它是独立的,可以正确处理错误,感觉更像是一个链接:

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

例如,您还可以在单​​击后将链接颜色更改为紫色,如果这看起来有用的话。它都是独立的,您只需调用:

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

【讨论】:

我刚刚添加了新的拉取请求以添加 uri setter 如果鼠标变成手就更好了! @Leon 看看我的答案顶部链接的版本,它使用setCursor(new Cursor(Cursor.HAND_CURSOR)); 并且对这个答案中的内联变体有一些其他改进。【参考方案3】:

您可以在

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

或者如果您想使用 Internet Explorer 或 Firefox,请将 chrome 替换为 iexplorefirefox

【讨论】:

【参考方案4】:

以下代码需要将JHyperLink 添加到您的构建路径中。

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

JComponent[] messageComponents = new JComponent[]  *** ;

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

请注意,您可以使用更多 Swing 组件填充 JComponent 数组。

结果:

【讨论】:

【参考方案5】:

只需输入window.open(website url),每次都有效。

【讨论】:

【参考方案6】:

我写了一篇关于如何在 jLabel 上设置超链接或 mailto 的文章。

所以试试it:

我认为这正是您要寻找的。​​p>

这是完整的代码示例:

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

【讨论】:

【参考方案7】:

使用JEditorPaneHyperlinkListener

【讨论】:

【参考方案8】:

我知道我参加聚会有点晚了,但我做了一些其他人可能会觉得很酷/有用的方法。

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;

它会给你一个 JLabel,就像一个正确的链接。

在行动:

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

如果您不希望任何工具提示,只需发送一个 null。

希望有人觉得这很有用! (如果您这样做,请务必让我知道,我很乐意听到。)

【讨论】:

【参考方案9】:

我想提供另一种解决方案。它类似于已经提出的那些,因为它在 JLabel 中使用 HTML 代码,并在其上注册了一个 MouseListener,但是当您将鼠标移到链接上时它还会显示一个 HandCursor,因此外观就像大多数用户所期望的那样.如果平台不支持浏览,则不会创建可能误导用户的蓝色下划线 HTML 链接。相反,该链接仅以纯文本形式呈现。 这可以与@dimo414 提出的 SwingLink 类结合使用。

public class JLabelLink extends JFrame 

private static final String LABEL_TEXT = "For further information visit:";
private static final String A_VALID_LINK = "http://***.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);
        
    );


【讨论】:

不在 EDT 上进行连接是一个很好的收获!需要修复 SwingX HyperlinkAction 以使其不这样做:-) 在 SwingX 中提交了一个问题:java.net/jira/browse/SWINGX-1530 - 感谢您提出这个问题 :-) @kleopatra 不客气 :) 看来您无法重现 Desktop.browse 的阻塞行为 - 在我的慢速机器上它确实会阻塞,尤其是在浏览器尚未打开的情况下. 好点!在问题中添加了您的评论 - 由于无法解决,几乎倾向于关闭,您的评论救了我:-) 这是一个有趣的解决方案。我喜欢它扩展 JLabel 的方式——这意味着 GroupLayout 更有可能将其定位为标签,而不是按钮。我注意到使用按钮似乎会增加组件之间的间距...【参考方案10】:

您可以使用JLabel 执行此操作,但另一种方法是设置JButton 的样式。这样,您就不必担心accessibility,只需使用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 */ 
  

【讨论】:

+1 交替使用JTextField,如this answer 所示。 即使是不属于链接的文字也可以点击链接。【参考方案11】:

您可以尝试使用 JEditorPane 而不是 JLabel。这了解基本的 HTML,并将向您在 JEditPane 中注册的 HyperlinkListener 发送一个 HyperlinkEvent 事件。

【讨论】:

如果您的文本中有一些超链接(可能会即时更改),这是最好的解决方案。大多数其他解决方案都需要将超链接放在单独的控件中。【参考方案12】:

如果 不起作用,那么:

    创建一个 JLabel 并添加一个 MouseListener(将标签装饰成超链接) 实现mouseClicked()事件 在mouseClicked()事件的实现中,执行你的动作

查看java.awt.Desktop API 以使用默认浏览器打开链接(此 API 仅适用于 Java6)。

【讨论】:

以上是关于如何在 JLabel 中添加超链接?的主要内容,如果未能解决你的问题,请参考以下文章

java超链接怎么实现?

如何在html中添加的图片上设置超链接

在空间发表说说的时候如何添加超链接 和在发表日志的时候如何HTML编辑格式插入超链接 和点击入口

超链接如何加下划线 css

android中,如何屏蔽WebView里的超链接?

jsp中如何给背景图上的超链接添加点击事件?