2010-08-27 9 views
8

A Swing JLabel interpreta automáticamente cualquier texto como contenido HTML, si comienza con <html>. Si el contenido de este HTML es una imagen con una URL no válida, esto hará que toda la GUI se cuelgue, ya que ImageFetche, que debería cargar esta imagen, se cerrará con un NPE.¿Cómo deshabilitar la compatibilidad automática con HTML de JLabel?

Para reproducir este problema basta con crear un JLabel de la siguiente manera

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

Sé que es una propiedad del cliente para evitar que el JLabel de interpretar HTML. Pero JLabel es la implementación de renderizador predeterminada para muchos componentes Swing (como JTree, JTable, etc.) lo que hace que esto sea un problema para casi cualquier aplicación Swing que permita la entrada del usuario. Entonces, en lugar de implementar toneladas de renderizador personalizado, estoy buscando una solución global para deshabilitar la interpretación de HTML.

+0

¿Qué impide que la solución 'putClientProperty' funcione? –

+1

putClientProperty funciona, pero hay muchos JLabels de los que uno puede no estar al tanto. Como ejemplo: crea una lista como nueva lista J (nueva cadena [] {"entrada"}). La 'entrada' será renderizada por un JLabel (vea javax.swing.DefaultListCellRenderer). No conozco ninguna solución genérica para evitar que los JLabels como este interpreten HTML. Si reemplaza 'entrada' por el HTML como se mencionó anteriormente, la GUI se bloqueará. – tigger

Respuesta

4

Hay una manera de crear su propia apariencia.
No estoy seguro de qué tan bien funciona esto, pero funciona. Supongamos que extenderá el "Windows clásico" L & F. Necesita al menos 2 clases Uno es el Look & Siéntete a sí mismo, vamos a llamarlo WindowsClassicLookAndFeelExt. Solo necesita reemplazar el método 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); 
    } 
} 

también necesita una clase WindowsLabelExtUI para gestionar todos JLabels y establezca la propiedad:

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

Y por último, una clase de prueba cuando se establece el tema como 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); 
    } 
} 

Y usted verá algo así como

alt text

2

Para un simple JLabel, puede llamar al método JComponent

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

en la etiqueta en la que desea desactivar la representación HTML.

Referencia: Impossible to disable HTML Rendering in a JLabel


Para algo así como un JTable, JTree o JList que necesita para crear un procesador de celdas personalizado que establece esta propiedad. Aquí hay un ejemplo (modificado desde this example) que crea un procesador de celdas personalizado para 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; 
    } 
} 

que utiliza el código de ejemplo de la documentación ListCellRenderer como punto de partida para el procesador de la lista de celdas personalizado.

Cuando ejecuto el ejemplo, puede ver que el HTML en la primera entrada de la lista se representa en lugar de interpretarse.

JList Custom Renderer

+0

Lo sé, pero esto no funciona para JLabels que se utilizan como TableCellRenderer, ListCellRenderer y demás, a menos que escriba mi propia implementación para cualquiera de ellos. – tigger

+0

"Sé que hay una propiedad del cliente para evitar que JLabel interprete HTML". – Epaga

0

colgante es probablemente el comportamiento desagradable menos. Es por eso que Data Validation es muy importante. Simplemente no permita que los usuarios ingresen algo así.

+3

Realmente creo que es el camino equivocado. –

+0

El manejo del html en los componentes Swing se delega a LAF. Por lo tanto, a menos que se implemente un LAF personalizado, no hay manera de deshabilitar globalmente el soporte para la etiqueta html. Y, no hay absolutamente ninguna razón para permitir la entrada arbitraria, no validada por el usuario. Eso es solo pedir problemas. En esencia, cada ataque de desbordamiento de búfer realmente se reduce a que alguien no pudo validar la entrada. OP ha demostrado cómo una entrada descuidada/desorientada puede colgar el sistema. Pero piense, ¿qué podría hacer un usuario malévolo? –

Cuestiones relacionadas