จะเพิ่มไฮเปอร์ลิงค์ใน JLabel ได้อย่างไร?


93

วิธีที่ดีที่สุดในการเพิ่มไฮเปอร์ลิงก์ใน JLabel คืออะไร ฉันสามารถดูได้โดยใช้แท็ก html แต่จะเปิดเบราว์เซอร์ได้อย่างไรเมื่อผู้ใช้คลิก



คุณสามารถหาวิธีง่ายๆได้ที่นี่: วิธีแก้ปัญหา
bench_doos

คำตอบ:


96

คุณสามารถทำได้โดยใช้ a JLabelแต่อีกทางเลือกหนึ่งคือจัดรูปแบบ a JButton. ด้วยวิธีนี้คุณไม่ต้องกังวลเกี่ยวกับการเข้าถึงและสามารถเริ่มเหตุการณ์โดยใช้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 สลับกันใช้ a JTextFieldดังที่แสดงในคำตอบนี้
Andrew Thompson

2
แม้แต่ข้อความที่ไม่ได้เป็นส่วนหนึ่งของลิงก์ก็สามารถคลิกเพื่อไปที่ลิงก์ได้
neuralmer

28

ฉันต้องการเสนอทางออกอื่น คล้ายกับสิ่งที่เสนอไปแล้วเนื่องจากใช้ HTML-code ใน JLabel และลงทะเบียน MouseListener แต่ยังแสดง HandCursor เมื่อคุณเลื่อนเมาส์ไปที่ลิงก์ดังนั้นรูปลักษณ์และความรู้สึกก็เหมือนกับที่ผู้ใช้ส่วนใหญ่คาดหวัง . หากแพลตฟอร์มไม่รองรับการท่องเว็บจะไม่มีการสร้างลิงค์ HTML สีน้ำเงินที่ขีดเส้นใต้ซึ่งอาจทำให้ผู้ใช้เข้าใจผิด แต่ลิงก์จะแสดงเป็นข้อความธรรมดา สิ่งนี้สามารถใช้ร่วมกับคลาส SwingLink ที่เสนอโดย @ 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
การไม่ทำการเชื่อมต่อกับ EDT เป็นการจับที่ยอดเยี่ยม! ต้องแก้ไข SwingX HyperlinkAction ไม่ให้ทำเช่นกัน :-)
kleopatra

ยื่นปัญหาใน SwingX: java.net/jira/browse/SWINGX-1530 - ขอบคุณที่แจ้งเรื่องนี้ :-)
kleopatra

@kleopatra ยินดีต้อนรับ :) ดูเหมือนว่าคุณไม่สามารถสร้างพฤติกรรมการบล็อกของ Desktop.browse ได้ - บนเครื่องที่ช้าของฉันมันจะบล็อกอย่างแน่นอนโดยเฉพาะอย่างยิ่งถ้าเบราว์เซอร์ยังไม่เปิด
Stefan

จุดดี! เพิ่มความคิดเห็นของคุณในปัญหา - เกือบจะปิดโดยไม่ได้รับการแก้ไขความคิดเห็นของคุณช่วยฉัน :-)
kleopatra

นี่เป็นทางออกที่น่าสนใจ ฉันชอบวิธีที่มันขยาย JLabel - ซึ่งหมายความว่า GroupLayout มีแนวโน้มที่จะวางตำแหน่งเหมือนป้ายกำกับไม่ใช่เหมือนปุ่ม ฉันสังเกตเห็นว่าการใช้ปุ่มดูเหมือนจะเพิ่มระยะห่างระหว่างส่วนประกอบต่างๆ ...
Trejkaz

17

ฉันเขียนบทความเกี่ยวกับวิธีตั้งค่าไฮเปอร์ลิงก์หรือ mailto บน jLabel

ดังนั้นเพียงแค่ลองมัน :

ฉันคิดว่านั่นคือสิ่งที่คุณกำลังค้นหา

นี่คือตัวอย่างโค้ดที่สมบูรณ์:

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

อัปเดตฉันได้จัดเตรียมSwingLinkคลาสเพิ่มเติมและเพิ่มคุณสมบัติอื่น ๆ สามารถดูสำเนาล่าสุดได้ที่นี่: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.java


คำตอบของ @ McDowell นั้นยอดเยี่ยม แต่มีหลายสิ่งที่สามารถปรับปรุงได้ ข้อความที่สะดุดตานอกเหนือจากไฮเปอร์ลิงก์สามารถคลิกได้และยังดูเหมือนปุ่มแม้ว่าสไตล์บางส่วนจะถูกเปลี่ยน / ซ่อน แม้ว่าความสามารถในการเข้าถึงเป็นสิ่งสำคัญ แต่ UI ที่สอดคล้องกันก็มีเช่นกัน

ดังนั้นฉันจึงรวบรวมคลาสเพื่อขยาย JLabel ตามรหัสของ McDowell มีอยู่ในตัวจัดการข้อผิดพลาดได้อย่างเหมาะสมและให้ความรู้สึกเหมือนลิงก์มากขึ้น:

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

1
ฉันเพิ่งเพิ่มคำขอดึงใหม่เพื่อเพิ่ม uri setter
boly38

ถ้าเมาส์กลายเป็นมือได้จะยิ่งดี!
Leon

@ Leon ดูเวอร์ชันที่เชื่อมโยงที่ด้านบนของคำตอบของฉันซึ่งใช้setCursor(new Cursor(Cursor.HAND_CURSOR));และมีการปรับปรุงอื่น ๆ สำหรับตัวแปรอินไลน์ในคำตอบนี้
dimo414


13

คุณอาจลองใช้ JEditorPane แทน JLabel สิ่งนี้เข้าใจ HTML พื้นฐานและจะส่งเหตุการณ์ HyperlinkEvent ไปยัง HyperlinkListener ที่คุณลงทะเบียนกับ JEditPane


1
นี่เป็นทางออกที่ดีที่สุดหากคุณมีข้อความที่มีไฮเปอร์ลิงก์อยู่ในนั้น (อาจมีการเปลี่ยนแปลงได้ทันที) โซลูชันอื่น ๆ ส่วนใหญ่ต้องการการวางไฮเปอร์ลิงก์ในตัวควบคุมแยกต่างหาก
user149408

5

หาก <a href="link"> ไม่ทำงานแสดงว่า:

  1. สร้าง JLabel และเพิ่ม MouseListener (ตกแต่งฉลากให้ดูเหมือนไฮเปอร์ลิงก์)
  2. ใช้mouseClicked ()เหตุการณ์
  3. ในการดำเนินการ mouseClicked () เหตุการณ์ให้ดำเนินการของคุณ

มองไปที่ java.awt.Desktop API สำหรับการเปิดลิงก์โดยใช้เบราว์เซอร์เริ่มต้น (API นี้พร้อมใช้งานจาก Java6 เท่านั้น)


4

ฉันรู้ว่าฉันไปปาร์ตี้ช้า แต่ฉันทำวิธีการเล็กน้อยที่คนอื่นอาจคิดว่าเจ๋ง / มีประโยชน์

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

หากคุณไม่ต้องการคำแนะนำเครื่องมือเพียงแค่ส่งค่าว่าง

หวังว่าจะมีคนพบว่าสิ่งนี้มีประโยชน์! (ถ้าคุณเป็นเช่นนั้นโปรดแจ้งให้เราทราบเรายินดีที่จะรับฟัง)




1

ต้องJHyperLinkเพิ่มรหัสต่อไปนี้ในเส้นทางการสร้างของคุณ

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

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

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

โปรดทราบว่าคุณสามารถเติมJComponentอาร์เรย์ด้วยSwingส่วนประกอบเพิ่มเติมได้

ผลลัพธ์:


0

คุณสามารถใช้สิ่งนี้ภายใต้ไฟล์

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

หรือหากคุณต้องการใช้ Internet Explorer หรือ Firefox แทนที่chromeด้วยiexploreหรือfirefox

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.