2010-08-27 16 views
8

Uno Swing JLabel interpreta automaticamente qualsiasi testo come contenuto HTML, se inizia con <html>. Se il contenuto di questo HTML è un'immagine con URL non valido, ciò causerà l'interruzione dell'intera GUI poiché ImageFetche che dovrebbe caricare l'immagine verrà chiusa da un NPE.Come disabilitare il supporto HTML automatico di JLabel?

Per riprodurre il problema è sufficiente creare un JLabel come segue

new JLabel("<html><img src='http:\\\\invalid\\url'>") 

So che c'è una proprietà client per evitare che il JLabel di interpretare HTML. Ma JLabel è l'implementazione predefinita del renderizzatore per molti componenti di Swing (come JTree, JTable e così via) che rende questo un problema per quasi tutte le applicazioni Swing che consente l'input dell'utente. Quindi, invece di implementare tonnellate di renderer personalizzati, sto cercando una soluzione globale per disabilitare l'interpretazione HTML.

+0

Cosa impedisce la soluzione 'putClientProperty'? –

+1

putClientProperty funziona - ma ci sono molti JLabels di cui uno potrebbe non essere a conoscenza. Ad esempio: creare un elenco come nuovo JList (new String [] {"entry"}). La 'voce' sarà resa da una JLabel (vedi javax.swing.DefaultListCellRenderer). Non conosco nessuna soluzione generica per impedire a JLabels come questo di interpretare l'HTML. Se si sostituisce 'entry' con l'HTML come menzionato sopra, la GUI si bloccherà. – tigger

risposta

4

C'è un modo se si crea il proprio look and feel.
Non sono sicuro di quanto funzioni questo risultato, ma funziona. Supponiamo che estendiate le "finestre classiche" L & F.È necessario alle classi 2 di leas 2 Uno è il look & Sentirsi, chiamiamolo WindowsClassicLookAndFeelExt. Devi solo eseguire l'override del metodo initClassDefaults.

package testSwing; 

import javax.swing.UIDefaults; 
import com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel; 

public class WindowsClassicLookAndFeelExt extends WindowsClassicLookAndFeel { 
    @Override protected void initClassDefaults(UIDefaults table){ 
     super.initClassDefaults(table); 
     Object[] uiDefaults = { "LabelUI", WindowsLabelExtUI.class.getCanonicalName()}; 
     table.putDefaults(uiDefaults); 
    } 
} 

È inoltre necessario un classe WindowsLabelExtUI per gestire tutte le JLabels e impostare la proprietà:

package testSwing; 
import javax.swing.JComponent; 
import javax.swing.plaf.ComponentUI; 
import com.sun.java.swing.plaf.windows.WindowsLabelUI; 

public class WindowsLabelExtUI extends WindowsLabelUI{ 
    static WindowsLabelExtUI singleton = new WindowsLabelExtUI(); 

    public static ComponentUI createUI(JComponent c){ 
     c.putClientProperty("html.disable", Boolean.TRUE);  
     return singleton; 
    } 
} 

E infine una classe di test quando si imposta il tema come WindowsClassicLookAndFeelExt

package testSwing; 

import java.awt.FlowLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JList; 
import javax.swing.JScrollPane; 
import javax.swing.UIManager; 


public class Main{ 
    public static void main(String[] args){ 
     try{    UIManager.setLookAndFeel(WindowsClassicLookAndFeelExt.class.getCanonicalName()); 
     }catch (Exception e){ 
      e.printStackTrace(); 
     } 

     JFrame frame = new JFrame("JList Test"); 
     frame.setLayout(new FlowLayout()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     String[] selections = {"<html><img src='http:\\\\invalid\\url'>", "<html><H1>Hello</h1></html>", "orange", "dark blue"}; 

     JList list = new JList(selections); 

     list.setSelectedIndex(1); 
     System.out.println(list.getSelectedValue()); 

     JLabel jLabel = new JLabel("<html><h2>standard Label</h2></html>"); 
     frame.add(new JScrollPane(list)); 
     frame.add(jLabel); 
     frame.pack(); 

     frame.setVisible(true); 
    } 
} 

E voi vedrà qualcosa come

alt text

2

Per una semplice JLabel, è possibile chiamare il metodo JComponent

myLabel.putClientProperty("html.disable", Boolean.TRUE); 

sull'etichetta in cui si desidera disabilitare il rendering HTML.

Riferimento: Impossible to disable HTML Rendering in a JLabel


per qualcosa come un JTable, Jtree o JList è necessario creare un renderer di celle personalizzato che imposta questa proprietà. Ecco un esempio (modificato da this example) che crea un renderer di celle personalizzato per un JList.

import java.awt.Component; 
import java.awt.FlowLayout; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JList; 
import javax.swing.JScrollPane; 
import javax.swing.ListCellRenderer; 

public class JListTest { 
    public static void main(String[] args) { 
     JFrame.setDefaultLookAndFeelDecorated(true); 
     JFrame frame = new JFrame("JList Test"); 
     frame.setLayout(new FlowLayout()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     String[] selections = { "<html><img src='http:\\\\invalid\\url'>", 
       "red", "orange", "dark blue" }; 
     JList list = new JList(selections); 

     // set the list cell renderer to the custom class defined below 
     list.setCellRenderer(new MyCellRenderer()); 

     list.setSelectedIndex(1); 
     System.out.println(list.getSelectedValue()); 
     frame.add(new JScrollPane(list)); 
     frame.pack(); 

     frame.setVisible(true); 
    } 
} 


class MyCellRenderer extends JLabel implements ListCellRenderer { 
    public MyCellRenderer() { 
     setOpaque(true); 
     putClientProperty("html.disable", Boolean.TRUE); 
    } 

    public Component getListCellRendererComponent(
     JList list, 
     Object value, 
     int index, 
     boolean isSelected, 
     boolean cellHasFocus) 
    { 
     setText(value.toString()); 
     return this; 
    } 
} 

ho usato il codice di esempio dalla documentazione ListCellRenderer come punto di partenza per il renderer personalizzato cellule lista.

Quando si esegue l'esempio, è possibile visualizzare che l'HTML nella prima voce dell'elenco viene eseguito il rendering anziché essere interpretato.

JList Custom Renderer

+0

Lo so - ma questo non funziona con JLabels che vengono usati come TableCellRenderer, ListCellRenderer e così via, a meno che non scriva la mia implementazione per nessuno di essi. – tigger

+0

"So che esiste una proprietà client per impedire a JLabel di interpretare HTML." – Epaga

0

sospensione è probabilmente il comportamento sgradevole almeno. Questo è il motivo per cui Data Validation è molto importante. Non permettere agli utenti di inserire qualcosa di simile.

+3

Penso davvero che sia il modo sbagliato. –

+0

La gestione del codice html nei componenti Swing è delegata alla LAF.So, a meno di implementare un LAF personalizzato, non è possibile disabilitare globalmente il supporto per il tag html. E, non c'è assolutamente alcun motivo per consentire l'input dell'utente arbitrario, non convalidato. Questo è solo un problema. Al centro, ogni exploit di buffer overflow si riduce in realtà a qualcuno che non riesce a convalidare l'input. OP ha dimostrato come un input incurante/indiscreto possa appendere il sistema. Ma considera, cosa potrebbe fare un utente malevolo? –

Problemi correlati