Qual é a melhor maneira de adicionar um hiperlink em um JLabel? Posso obter a visualização usando tags html, mas como abrir o navegador quando o usuário clica nele?
solução simples que você pode encontrar aqui: solução
bench_doos
Respostas:
97
Você pode fazer isso usando a JLabel, mas uma alternativa seria estilizar a JButton. Dessa forma, você não precisa se preocupar com a acessibilidade e pode apenas disparar eventos usando um ActionListener.
publicstaticvoid main(String[] args)throwsURISyntaxException{final URI uri =new URI("http://java.sun.com");classOpenUrlActionimplementsActionListener{@Overridepublicvoid actionPerformed(ActionEvent e){
open(uri);}}JFrame frame =newJFrame("Links");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(100,400);Container container = frame.getContentPane();
container.setLayout(newGridBagLayout());JButton button =newJButton();
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(newOpenUrlAction());
container.add(button);
frame.setVisible(true);}privatestaticvoid open(URI uri){if(Desktop.isDesktopSupported()){try{Desktop.getDesktop().browse(uri);}catch(IOException e){/* TODO: error handling */}}else{/* TODO: error handling */}}
+1 Como alternativa, use a JTextFieldconforme mostrado nesta resposta .
Andrew Thompson
1
Mesmo o texto que não faz parte do link pode ser clicado para seguir o link.
neuralmer
28
Eu gostaria de oferecer mais uma solução. É semelhante aos já propostos, pois usa código HTML em um JLabel e registra um MouseListener nele, mas também exibe um HandCursor quando você move o mouse sobre o link, de modo que a aparência é exatamente como a maioria dos usuários esperaria . Se a navegação não for suportada pela plataforma, nenhum link HTML sublinhado em azul é criado, o que pode enganar o usuário. Em vez disso, o link é apresentado apenas como texto simples. Isso pode ser combinado com a classe SwingLink proposta por @ dimo414.
publicclassJLabelLinkextendsJFrame{privatestaticfinalString LABEL_TEXT ="For further information visit:";privatestaticfinalString A_VALID_LINK ="http://stackoverflow.com";privatestaticfinalString A_HREF ="<a href=\"";privatestaticfinalString HREF_CLOSED ="\">";privatestaticfinalString HREF_END ="</a>";privatestaticfinalString HTML ="<html>";privatestaticfinalString HTML_END ="</html>";publicJLabelLink(){
setTitle("HTML link via a JLabel");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);Container contentPane = getContentPane();
contentPane.setLayout(newFlowLayout(FlowLayout.LEFT));JLabel label =newJLabel(LABEL_TEXT);
contentPane.add(label);
label =newJLabel(A_VALID_LINK);
contentPane.add(label);if(isBrowsingSupported()){
makeLinkable(label,newLinkMouseListener());}
pack();}privatestaticvoid 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);}privatestaticboolean isBrowsingSupported(){if(!Desktop.isDesktopSupported()){returnfalse;}boolean result =false;Desktop desktop = java.awt.Desktop.getDesktop();if(desktop.isSupported(Desktop.Action.BROWSE)){
result =true;}return result;}privatestaticclassLinkMouseListenerextendsMouseAdapter{@Overridepublicvoid mouseClicked(java.awt.event.MouseEvent evt){JLabel l =(JLabel) evt.getSource();try{
URI uri =new java.net.URI(JLabelLink.getPlainLink(l.getText()));(newLinkRunner(uri)).execute();}catch(URISyntaxException use){thrownewAssertionError(use +": "+ l.getText());//NOI18N}}}privatestaticclassLinkRunnerextendsSwingWorker<Void,Void>{privatefinal URI uri;privateLinkRunner(URI u){if(u ==null){thrownewNullPointerException();}
uri = u;}@OverrideprotectedVoid doInBackground()throwsException{Desktop desktop = java.awt.Desktop.getDesktop();
desktop.browse(uri);returnnull;}@Overrideprotectedvoid done(){try{
get();}catch(ExecutionException ee){
handleException(uri, ee);}catch(InterruptedException ie){
handleException(uri, ie);}}privatestaticvoid 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);}}privatestaticString 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 escapingprivatestaticString 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 escapingprivatestaticString htmlIfy(String s){return HTML.concat(s).concat(HTML_END);}/**
* @param args the command line arguments
*/publicstaticvoid main(String[] args){SwingUtilities.invokeLater(newRunnable(){@Overridepublicvoid run(){newJLabelLink().setVisible(true);}});}}
@kleopatra De nada :) Parece que você não conseguiu reproduzir o comportamento de bloqueio do Desktop.browse - na minha máquina lenta ele bloqueia com certeza, principalmente se o navegador ainda não estiver aberto.
Stefan
bom ponto! adicionou seu comentário ao problema - quase tendeu a fechar porque não corrige, seu comentário me salvou :-)
kleopatra
Esta é uma solução interessante. Gosto de como ele estende o JLabel - isso significa que o GroupLayout provavelmente o posicionará como um rótulo, não como um botão. Percebi que o uso de botões parece aumentar o espaçamento que você obtém entre os componentes ...
Trejkaz
17
Escrevi um artigo sobre como definir um hiperlink ou mailto em um jLabel.
A resposta de @McDowell é ótima, mas há várias coisas que podem ser melhoradas. Notavelmente, o texto diferente do hiperlink é clicável e ainda parece um botão, embora parte do estilo tenha sido alterado / oculto. Embora a acessibilidade seja importante, uma IU coerente também é.
Então, eu montei uma classe que estende JLabel com base no código de McDowell. É independente, lida com erros de maneira adequada e parece mais um link:
publicclassSwingLinkextendsJLabel{privatestaticfinallong serialVersionUID =8273875024682878518L;privateString text;private URI uri;publicSwingLink(String text, URI uri){super();
setup(text,uri);}publicSwingLink(String text,String uri){super();
setup(text,URI.create(uri));}publicvoid setup(String t, URI u){
text = t;
uri = u;
setText(text);
setToolTipText(uri.toString());
addMouseListener(newMouseAdapter(){publicvoid mouseClicked(MouseEvent e){
open(uri);}publicvoid mouseEntered(MouseEvent e){
setText(text,false);}publicvoid mouseExited(MouseEvent e){
setText(text,true);}});}@Overridepublicvoid setText(String text){
setText(text,true);}publicvoid 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;}publicString getRawText(){return text;}privatestaticvoid 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);}}}
Você também pode, por exemplo, alterar a cor do link para roxo depois de ser clicado, se isso parecer útil. É tudo independente, você simplesmente chama:
SwingLink link =newSwingLink("Java","http://java.sun.com");
mainPanel.add(link);
Acabei de adicionar uma nova solicitação de pull para adicionar uri setter
boly38
Se o mouse virar mão, será ainda melhor!
Leon
@Leon dê uma olhada na versão vinculada no topo da minha resposta, ela usa setCursor(new Cursor(Cursor.HAND_CURSOR));e tem algumas outras melhorias em relação à variante inline nesta resposta.
dimo414
14
Talvez usar JXHyperlinkde SwingX vez. Ele se estende JButton. Alguns links úteis:
Você pode tentar usar um JEditorPane em vez de um JLabel. Isso entende HTML básico e enviará um evento HyperlinkEvent para o HyperlinkListener que você registrar no JEditPane.
Esta é a melhor solução se você tiver texto com alguns hiperlinks (possivelmente alterados rapidamente). A maioria das outras soluções exige a colocação do hiperlink em um controle separado.
user149408
5
Se <a href="link"> não funcionar, então:
Crie um JLabel e adicione um MouseListener (decore o rótulo para se parecer com um hiperlink)
Respostas:
Você pode fazer isso usando a
JLabel
, mas uma alternativa seria estilizar aJButton
. Dessa forma, você não precisa se preocupar com a acessibilidade e pode apenas disparar eventos usando umActionListener
.fonte
JTextField
conforme mostrado nesta resposta .Eu gostaria de oferecer mais uma solução. É semelhante aos já propostos, pois usa código HTML em um JLabel e registra um MouseListener nele, mas também exibe um HandCursor quando você move o mouse sobre o link, de modo que a aparência é exatamente como a maioria dos usuários esperaria . Se a navegação não for suportada pela plataforma, nenhum link HTML sublinhado em azul é criado, o que pode enganar o usuário. Em vez disso, o link é apresentado apenas como texto simples. Isso pode ser combinado com a classe SwingLink proposta por @ dimo414.
fonte
Escrevi um artigo sobre como definir um hiperlink ou mailto em um jLabel.
Então, basta tentar isso :
Acho que é exatamente isso que você está procurando.
Aqui está o exemplo de código completo:
fonte
Atualização Eu organizei ainda mais a
SwingLink
classe e adicionei mais recursos; uma cópia atualizada pode ser encontrada aqui: https://bitbucket.org/dimo414/jgrep/src/tip/src/grep/SwingLink.javaA resposta de @McDowell é ótima, mas há várias coisas que podem ser melhoradas. Notavelmente, o texto diferente do hiperlink é clicável e ainda parece um botão, embora parte do estilo tenha sido alterado / oculto. Embora a acessibilidade seja importante, uma IU coerente também é.
Então, eu montei uma classe que estende JLabel com base no código de McDowell. É independente, lida com erros de maneira adequada e parece mais um link:
Você também pode, por exemplo, alterar a cor do link para roxo depois de ser clicado, se isso parecer útil. É tudo independente, você simplesmente chama:
fonte
setCursor(new Cursor(Cursor.HAND_CURSOR));
e tem algumas outras melhorias em relação à variante inline nesta resposta.Talvez usar
JXHyperlink
de SwingX vez. Ele se estendeJButton
. Alguns links úteis:fonte
Você pode tentar usar um JEditorPane em vez de um JLabel. Isso entende HTML básico e enviará um evento HyperlinkEvent para o HyperlinkListener que você registrar no JEditPane.
fonte
Se <a href="link"> não funcionar, então:
Dê uma olhada na API java.awt.Desktop para abrir um link usando o navegador padrão (esta API está disponível apenas no Java6).
fonte
Sei que estou meio atrasado para a festa, mas criei um pequeno método que outros podem achar legal / útil.
Isso lhe dará um JLabel que atua como um link adequado.
Em ação:
Se você não quiser nenhuma dica, envie um nulo.
Espero que alguém ache isso útil! (Se o fizer, não se esqueça de me avisar, terei todo o gosto em saber.)
fonte
Use um
JEditorPane
com umHyperlinkListener
.fonte
Basta colocar
window.open(website url)
, funciona sempre.fonte
O código a seguir precisa
JHyperLink
ser adicionado ao seu caminho de construção.Observe que você pode preencher a
JComponent
matriz com maisSwing
componentes.Resultado:
fonte
Você pode usar isso em um
ou se você quiser usar o Internet Explorer ou o Firefox, substitua
chrome
poriexplore
oufirefox
fonte