Jaki jest najlepszy sposób dodania hiperłącza w JLabel? Mogę uzyskać widok za pomocą tagów html, ale jak otworzyć przeglądarkę, gdy użytkownik ją kliknie?
Możesz to zrobić za pomocą a JLabel, ale alternatywą byłoby nadanie stylu a JButton. W ten sposób nie musisz martwić się o dostępność i możesz po prostu uruchamiać zdarzenia przy użyciu pliku ActionListener.
publicstaticvoidmain(String[] args)throws URISyntaxException {
final URI uri = new URI("http://java.sun.com");
classOpenUrlActionimplementsActionListener{
@OverridepublicvoidactionPerformed(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);
}
privatestaticvoidopen(URI uri){
if (Desktop.isDesktopSupported()) {
try {
Desktop.getDesktop().browse(uri);
} catch (IOException e) { /* TODO: error handling */ }
} else { /* TODO: error handling */ }
}
+1 Alternatywnie użyj JTextFieldjak pokazano w tej odpowiedzi .
Andrew Thompson,
2
Nawet tekst, który nie jest częścią łącza, można kliknąć, aby przejść do łącza.
neuralmer
28
Chciałbym zaproponować jeszcze inne rozwiązanie. Jest podobny do już proponowanych, ponieważ wykorzystuje kod HTML w JLabel i rejestruje na nim MouseListener, ale wyświetla również HandCursor po najechaniu kursorem myszy na łącze, więc wygląd i styl są takie, jakich oczekuje większość użytkowników . Jeśli przeglądanie nie jest obsługiwane przez platformę, nie jest tworzony niebieski, podkreślony link HTML, który mógłby wprowadzić użytkownika w błąd. Zamiast tego łącze jest przedstawiane jako zwykły tekst. Można to połączyć z klasą SwingLink zaproponowaną przez @ dimo414.
publicclassJLabelLinkextendsJFrame{
privatestaticfinal String LABEL_TEXT = "For further information visit:";
privatestaticfinal String A_VALID_LINK = "http://stackoverflow.com";
privatestaticfinal String A_HREF = "<a href=\"";
privatestaticfinal String HREF_CLOSED = "\">";
privatestaticfinal String HREF_END = "</a>";
privatestaticfinal String HTML = "<html>";
privatestaticfinal String HTML_END = "</html>";
publicJLabelLink(){
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();
}
privatestaticvoidmakeLinkable(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);
}
privatestaticbooleanisBrowsingSupported(){
if (!Desktop.isDesktopSupported()) {
returnfalse;
}
boolean result = false;
Desktop desktop = java.awt.Desktop.getDesktop();
if (desktop.isSupported(Desktop.Action.BROWSE)) {
result = true;
}
return result;
}
privatestaticclassLinkMouseListenerextendsMouseAdapter{
@OverridepublicvoidmouseClicked(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) {
thrownew AssertionError(use + ": " + l.getText()); //NOI18N
}
}
}
privatestaticclassLinkRunnerextendsSwingWorker<Void, Void> {
privatefinal URI uri;
privateLinkRunner(URI u){
if (u == null) {
thrownew NullPointerException();
}
uri = u;
}
@Overrideprotected Void doInBackground()throws Exception {
Desktop desktop = java.awt.Desktop.getDesktop();
desktop.browse(uri);
returnnull;
}
@Overrideprotectedvoiddone(){
try {
get();
} catch (ExecutionException ee) {
handleException(uri, ee);
} catch (InterruptedException ie) {
handleException(uri, ie);
}
}
privatestaticvoidhandleException(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);
}
}
privatestatic 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 escapingprivatestatic 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 escapingprivatestatic String htmlIfy(String s){
return HTML.concat(s).concat(HTML_END);
}
/**
* @param args the command line arguments
*/publicstaticvoidmain(String[] args){
SwingUtilities.invokeLater(new Runnable() {
@Overridepublicvoidrun(){
new JLabelLink().setVisible(true);
}
});
}
}
@kleopatra Nie ma za co :) Wygląda na to, że nie możesz odtworzyć zachowania blokującego Desktop.browse - na moim wolnym komputerze na pewno blokuje, zwłaszcza jeśli przeglądarka nie jest jeszcze otwarta.
Stefan
Słuszna uwaga! dodał twój komentarz do sprawy - prawie prawie się zamykał, bo nie naprawi, twój komentarz mnie uratował :-)
kleopatra
To ciekawe rozwiązanie. Podoba mi się, jak rozszerza JLabel - oznacza to, że GroupLayout z większym prawdopodobieństwem umieści go jako etykietę, a nie jak przycisk. Zauważyłem, że użycie przycisków wydaje się zwiększać odstępy między komponentami ...
Trejkaz
17
Napisałem artykuł o tym, jak ustawić hiperłącze lub mailto w jLabel.
Odpowiedź @ McDowell jest świetna, ale jest kilka rzeczy, które można poprawić. W szczególności tekst inny niż hiperłącze jest klikalny i nadal wygląda jak przycisk, mimo że niektóre style zostały zmienione / ukryte. Chociaż dostępność jest ważna, spójny interfejs użytkownika jest również ważny.
Więc stworzyłem klasę rozszerzającą JLabel w oparciu o kod McDowella. Jest samowystarczalny, poprawnie obsługuje błędy i bardziej przypomina łącze:
publicclassSwingLinkextendsJLabel{
privatestaticfinallong serialVersionUID = 8273875024682878518L;
private String text;
private URI uri;
publicSwingLink(String text, URI uri){
super();
setup(text,uri);
}
publicSwingLink(String text, String uri){
super();
setup(text,URI.create(uri));
}
publicvoidsetup(String t, URI u){
text = t;
uri = u;
setText(text);
setToolTipText(uri.toString());
addMouseListener(new MouseAdapter() {
publicvoidmouseClicked(MouseEvent e){
open(uri);
}
publicvoidmouseEntered(MouseEvent e){
setText(text,false);
}
publicvoidmouseExited(MouseEvent e){
setText(text,true);
}
});
}
@OverridepublicvoidsetText(String text){
setText(text,true);
}
publicvoidsetText(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;
}
privatestaticvoidopen(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);
}
}
}
Możesz na przykład zmienić kolor łącza na fioletowy po kliknięciu, jeśli wydaje się to przydatne. To wszystko jest samodzielne, po prostu dzwonisz:
SwingLink link = new SwingLink("Java", "http://java.sun.com");
mainPanel.add(link);
Właśnie dodałem nową prośbę o ściągnięcie, aby dodać
ustawienie URI
Jeśli mysz stanie się ręką, będzie jeszcze lepiej!
Leon
@Leon spójrz na wersję, do której link znajduje się u góry mojej odpowiedzi, używa setCursor(new Cursor(Cursor.HAND_CURSOR));i ma kilka innych ulepszeń w stosunku do wariantu wbudowanego w tej odpowiedzi.
dimo414
14
Może korzystać JXHyperlinkz SwingX zamiast. To się rozciąga JButton. Kilka przydatnych linków:
Możesz spróbować użyć JEditorPane zamiast JLabel. Rozumie podstawowy HTML i wyśle zdarzenie HyperlinkEvent do HyperlinkListener, który zarejestrujesz w JEditPane.
To najlepsze rozwiązanie, jeśli masz tekst z kilkoma hiperłączami (prawdopodobnie zmienianymi w locie). Większość innych rozwiązań wymaga umieszczenia hiperłącza w osobnej kontrolce.
user149408
5
Jeśli <a href="link"> nie działa, to:
Utwórz JLabel i dodaj MouseListener (udekoruj etykietę, aby wyglądała jak hiperłącze)
Odpowiedzi:
Możesz to zrobić za pomocą a
JLabel
, ale alternatywą byłoby nadanie stylu aJButton
. W ten sposób nie musisz martwić się o dostępność i możesz po prostu uruchamiać zdarzenia przy użyciu plikuActionListener
.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 */ } }
źródło
JTextField
jak pokazano w tej odpowiedzi .Chciałbym zaproponować jeszcze inne rozwiązanie. Jest podobny do już proponowanych, ponieważ wykorzystuje kod HTML w JLabel i rejestruje na nim MouseListener, ale wyświetla również HandCursor po najechaniu kursorem myszy na łącze, więc wygląd i styl są takie, jakich oczekuje większość użytkowników . Jeśli przeglądanie nie jest obsługiwane przez platformę, nie jest tworzony niebieski, podkreślony link HTML, który mógłby wprowadzić użytkownika w błąd. Zamiast tego łącze jest przedstawiane jako zwykły tekst. Można to połączyć z klasą SwingLink zaproponowaną przez @ 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); } }); } }
źródło
Napisałem artykuł o tym, jak ustawić hiperłącze lub mailto w jLabel.
Więc po prostu spróbować go :
Myślę, że właśnie tego szukasz.
Oto przykład pełnego kodu:
/** * 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 } } }); } }
źródło
Aktualizacja Uporządkowałem
SwingLink
klasę i dodałem więcej funkcji; jego aktualną kopię można znaleźć tutaj: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.javaOdpowiedź @ McDowell jest świetna, ale jest kilka rzeczy, które można poprawić. W szczególności tekst inny niż hiperłącze jest klikalny i nadal wygląda jak przycisk, mimo że niektóre style zostały zmienione / ukryte. Chociaż dostępność jest ważna, spójny interfejs użytkownika jest również ważny.
Więc stworzyłem klasę rozszerzającą JLabel w oparciu o kod McDowella. Jest samowystarczalny, poprawnie obsługuje błędy i bardziej przypomina łącze:
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); } } }
Możesz na przykład zmienić kolor łącza na fioletowy po kliknięciu, jeśli wydaje się to przydatne. To wszystko jest samodzielne, po prostu dzwonisz:
SwingLink link = new SwingLink("Java", "http://java.sun.com"); mainPanel.add(link);
źródło
setCursor(new Cursor(Cursor.HAND_CURSOR));
i ma kilka innych ulepszeń w stosunku do wariantu wbudowanego w tej odpowiedzi.Może korzystać
JXHyperlink
z SwingX zamiast. To się rozciągaJButton
. Kilka przydatnych linków:źródło
Możesz spróbować użyć JEditorPane zamiast JLabel. Rozumie podstawowy HTML i wyśle zdarzenie HyperlinkEvent do HyperlinkListener, który zarejestrujesz w JEditPane.
źródło
Jeśli <a href="link"> nie działa, to:
Zajrzyj do interfejsu API java.awt.Desktop, aby otworzyć łącze za pomocą domyślnej przeglądarki (to API jest dostępne tylko w Javie6).
źródło
Wiem, że jestem trochę spóźniony na imprezę, ale stworzyłem małą metodę, którą inni mogą uznać za fajną / przydatną.
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; }
Otrzymasz JLabel, który działa jak właściwy link.
W akcji:
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); }
Jeśli nie chcesz żadnej podpowiedzi, po prostu wyślij null.
Mam nadzieję, że ktoś uzna to za przydatne! (Jeśli tak, daj mi znać, z przyjemnością usłyszę).
źródło
Użyj
JEditorPane
z aHyperlinkListener
.źródło
Mówiąc krótko
window.open(website url)
, działa za każdym razem.źródło
Poniższy kod wymaga
JHyperLink
dodania do ścieżki kompilacji.JHyperlink stackOverflow = new JHyperlink("Click HERE!", "https://www.stackoverflow.com/"); JComponent[] messageComponents = new JComponent[] { stackOverflow }; JOptionPane.showMessageDialog(null, messageComponents, "StackOverflow", JOptionPane.PLAIN_MESSAGE);
Zauważ, że możesz wypełnić
JComponent
tablicę większą liczbąSwing
składników.Wynik:
źródło
Możesz użyć tego w
actionListener -> Runtime.getRuntime().exec("cmd.exe /c start chrome www.google.com")`
lub jeśli chcesz korzystać z Internet Explorer lub Firefox zastąpić
chrome
ziexplore
lubfirefox
źródło