2012-02-22 23 views
10

Próbuję wyświetlić obraz wbudowany w Java JEditorPane. Poniższy kod wykorzystuje treść HTML, która poprawnie wyświetla obraz w przeglądarce Firefox, ale nie w JEditorPane. Jakieś pomysły, dlaczego? Dzięki.JEditorPane z obrazem w wierszu

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

Odpowiedz

15

Musisz dodać procedurę obsługi protokołu dla "data:", aby można było otworzyć dla niej URL/URLConnection. Alternatywnie możesz utworzyć moduł obsługi protokołu "resource:" dla zasobów ścieżek klas.

Potrzebujesz pakietu data z klasą Handler (konwencja o ustalonej nazwie!). Będzie to klasa fabryczna dla "data:" zwraca URLConnection. Stworzymy dla tego DataConnection.

Instalowanie procedury obsługi protokołu można wykonać za pomocą System.setProperty. Tutaj podałem Handler.install();, aby zrobić to w sposób ogólny.

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

URLConnection daje InputStream do bajtów:

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

} 

Pomysłowa rzeczą jest użycie Base64 dekodowanie DatatypeConverter w standardzie Java SE.


PS:

W dzisiejszych czasach można użyć Base64.getEncoder().encode(...).

+0

* "Sprytna rzecz tutaj" * Zobaczyłem 4 rzeczy, które sprawiły, że pomyślałem - Wow, to sprytnie! Moje "przedmioty do nauki" danego dnia. :) –

+0

Dziękuję za szczegółową odpowiedź! Spróbuję tego. – Mike

+0

Pracował jak urok! Wielkie dzięki. Zbadanie twojej odpowiedzi postawiło jedno pytanie. Znalazłem kilka odniesień do faktu, że właściwość java.protocol.handler.pkgs jest odczytywana przez maszynę JVM podczas uruchamiania, więc procedury obsługi muszą być dostarczone w wierszu poleceń (na przykład java -Djava.protocol.handler.pkgs = xxxxxx). Ale po prostu wywołałem test1.data.Handler.install() w mojej metodzie main() i zadziałało. Czy zachowanie zostało zmienione w nowszych wersjach Java, czy też po prostu źle się z nim przeczytałem? – Mike