2012-02-22 42 views
10

Estoy intentando mostrar una imagen en línea en Java JEditorPane. El siguiente código utiliza contenido HTML que muestra correctamente la imagen en Firefox, pero no en el JEditorPane. ¿Alguna idea de por qué? Gracias.JEditorPane con imagen en línea

import javax.swing.*; 
import java.awt.*; 

public class InlineImage { 

    public InlineImage() { 
     JFrame frame=new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JEditorPane edit=new JEditorPane(); 
     frame.getContentPane().add(edit); 
     edit.setContentType("text/html"); 

     String html = "<html><body>Local image<br><img src=\"data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAyCAYAAACqNX6+AAACeklEQVR42u1bHZBCURgNgiBYCINgIVhYCIKFhSBYCIIgCIKFxSBoZpsJgjAIgmAhCIIgCIKFIAiChSAIF4IgCL7d82abnWl69Xq9+7r1Dhyp93PfOff7ufd+n8/nEyF0AkmgIAQFoSDEjQgSCn1LPD6SbPZDSqWKNBqv0m5nZDh8lsnkUebziIH1OiC/d+wF/tteN50+GPfiGbVaQcrld8nnm8Y78C4K8odAYC3R6Jfkci2pVosGaYtFWDYbvynRKgDx8G4Ij7FgTBjbzQuC2ZhOd4wZCgIOzfBLYysSxooxh8OL2xAEH4KPGo3irs98pwF3CZcXi42vS5CtCPiAaxfBDLPZvRQKNUWW49CDEomBdDrpmxXBDN1uSlKprvj9m8sLgkHAx47HMU+JYObSkBmenxDYvDGTaRum63UhdoFUG9maa4IgW4KZkvzD6PVebMaYEy6GSS6XdyTcIlaroA1rsRgr6vU3zwVsp4BFZzC4ckYQBCmYH4k9D4NBwmLAP2IZFMNZUY6nxwf+rFRKJNJhYLVvSxAs9Bgz1ADcniQIzIprDLVbL+aua8+PyWSfxCkGOLYsSKuVI2mKAY4tC4LlP0lTv8ViWRAS5g4oyLUKQpelmctiUNcsqDPt1Szt5cJQs4Uht0402zrh5qKGm4tb19XvJ0mkq2ciPKC6ngOq3SNcEms/xXXsCJdFDhoWOeyWAdGFWSsDikTm7hXKwVq4VjEvlLNfWnpmKSkqGFlK+l9Kaj1WuFBs7cWKRrgmbYqtvdyOUCxW9W5HOCQOXBobdtjSxpY2J5o+L0W+55o+7bZFN5t5JW3RT0+fbIsmKAgFISgIBSHU4QdCoO0W7Xd4AwAAAABJRU5ErkJggg==\"></body></html>"; 
     edit.setText(html); 

     frame.setSize(500,300); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) {new InlineImage();} 
} 

Respuesta

15

es necesario agregar un controlador de protocolo para "data:" por lo que un URL/URLConnection se puede abrir para él. De forma alternativa, podría crear algún "recurso: controlador de protocolo" para recursos de ruta de clase.

Necesita un paquete data con una clase Handler (convención de nombre fijo). Esta será la clase de fábrica para "datos:" devuelve una URLConnection. Crearemos DataConnection para eso.

La instalación de un controlador de protocolo se puede realizar a través de System.setProperty. Aquí proporcioné Handler.install(); para hacer eso de una manera genérica.

package test1.data; 

import java.io.IOException; 
import java.net.URL; 
import java.net.URLConnection; 
import java.net.URLStreamHandler; 

public class Handler extends URLStreamHandler { 

    @Override 
    protected URLConnection openConnection(URL u) throws IOException { 
     return new DataConnection(u); 
    } 

    public static void install() { 
     String pkgName = Handler.class.getPackage().getName(); 
     String pkg = pkgName.substring(0, pkgName.lastIndexOf('.')); 

     String protocolHandlers = System.getProperty("java.protocol.handler.pkgs", ""); 
     if (!protocolHandlers.contains(pkg)) { 
      if (!protocolHandlers.isEmpty()) { 
       protocolHandlers += "|"; 
      } 
      protocolHandlers += pkg; 
      System.setProperty("java.protocol.handler.pkgs", protocolHandlers); 
     } 
    } 
} 

El URLConnection da un InputStream a los bytes:

package test1.data; 

import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.URL; 
import java.net.URLConnection; 
import javax.xml.bind.DatatypeConverter; 

public class DataConnection extends URLConnection { 

    public DataConnection(URL u) { 
     super(u); 
    } 

    @Override 
    public void connect() throws IOException { 
     connected = true; 
    } 

    @Override 
    public InputStream getInputStream() throws IOException { 
     String data = url.toString(); 
     data = data.replaceFirst("^.*;base64,", ""); 
     System.out.println("Data: " + data); 
     byte[] bytes = DatatypeConverter.parseBase64Binary(data); 
     return new ByteArrayInputStream(bytes); 
    } 

} 

Lo inteligente es usar la decodificación base 64 de DatatypeConverter en el estándar de Java SE.


P. S.

Hoy en día uno usaría Base64.getEncoder().encode(...).

+0

* "Lo inteligente aquí" * Vi alrededor de 4 cosas que me hicieron pensar: "¡Eso es inteligente! Mi 'aprender artículo (s)' del día. :) –

+0

¡Gracias por la respuesta detallada! Voy a intentar esto. – Mike

+0

¡Funcionó como un encanto! Muchas gracias. Investigar tu respuesta planteó una pregunta. Encontré varias referencias al hecho de que la propiedad java.protocol.handler.pkgs es leída por la JVM al inicio, por lo que los manejadores se deben proporcionar en la línea de comando (por ejemplo, java -Djava.protocol.handler.pkgs = xxxxxx). Pero simplemente llamé a test1.data.Handler.install() en mi método main() y funcionó. ¿Ha cambiado el comportamiento en las versiones más nuevas de Java, o simplemente lo leí mal? – Mike

Cuestiones relacionadas