3.14.13. Die Image Factory

Die Image Factory ermöglicht die Erzeugung von Images oder Buffered Images.

Die Schnittstelle `IImageFactory’ hat die folgenden Methoden:

    IImage createImage(File file);

    IImage createImage(URL url);

    IImage createImage(IFactory<InputStream> inputStream);

    IBufferedImage createBufferedImage(int width, int height);
Image Factory Instanz

Eine Instanz erhält man vom Toolkit mit Hilfe der folgenden Methode:

    IImageFactory getImageFactory();
Die Schnittstelle IImage

Die Schnittstelle IImage hat die folgenden Methoden:

    Dimension getSize();

    void initialize();

    void dispose();
    
    boolean isDisposed();
    
    void addDisposeListener(IDisposeListener listener);

    void removeDisposeListener(IDisposeListener listener);

Ein IImage ist von IImageConstant abgeleitet, und kann somit überall verwendet werden, wo Image Konstanten verwendet werden können.[25]

Wird ein Image (oder Buffered Image) von der Image Factory erzeugt, wird es automatisch in der Image Registry registriert, und ist somit für die Verwendung in Widgets unmittelbar verfügbar.

Das native Image (z.B. org.eclipse.swt.graphics.Image) wird erst erzeugt, wenn es einem Widget zugewiesen, oder die Methode getSize() oder initialize() aufgerufen wurde. Wird das Image mehrfach (für unterschiedliche Widgets) verwendet, wird trotzdem nur eine native Image Instanz erzeugt.

Wird die dispose() Methode auf dem Image aufgerufen, wird das Image automatisch aus der Image Registry entfernt und das zugehörige native Image disposed, falls es bereits initialisiert wurde. Das gleiche passiert, wenn auf der Image Registry die Methode unRegisterImage(...) für das Image aufgerufen wird. In beiden Fällen führen anschließend alle Operation auf dem Image (außer isDisposed()) zu einem Fehler.

Images können in jedem beliebigen Thread erzeugt werden. Für Images, welche explizit außerhalb des Ui Thread geladen werden sollen, sollte man darauf achten, dass ohne expliziten Aufruf der Methode initialize() nur ein Image Handle erzeugt wird, und das eigentliche Laden erst bei der ersten Verwendung im UI Thread stattfindet.

Die Schnittstelle IBufferedImage

Die Schnittstelle IBufferedImage ist von IImage abgeleitet. Zusätzlich zu den geerbten Methoden hat ein Bufferd Image die folgende weitere Methode:

    IGraphicContext getGraphicContext();

Ein Buffered Image liefert einen Graphic Context zum Zeichnen des Bildes.

Das ImageIconSnipped

Das ImageIconSnipped zeigt die Verwendung eines Images in Verbindung mit einem Icon Widget:

  1  public final class ImageIconSnipped implements IApplication {
  2  
  3      @Override
  4      public void start(final IApplicationLifecycle lifecycle) {
  5  
  6          //create the root frame
  7          final IFrame frame = Toolkit.createRootFrame(
  8              BPF.frame("Image Icon Snipped"), 
  9              lifecycle);
 10          frame.setLayout(FillLayout.get());
 11  
 12          //create a scroll composite
 13          final IScrollComposite container = frame.add(BPF.scrollComposite());
 14          container.setLayout(FillLayout.get());
 15  
 16          //create a image from url
 17          String url = "http://www.jowidgets.org/docu/images/widgets_hierarchy_1.gif";
 18          final IImage image = ImageFactory.createImage(UrlFactory.create(url));
 19  
 20          //use the icon widget to display the image
 21          final IIcon imageIcon = container.add(BPF.icon(image));
 22  
 23          //remove the icon on double click from its container to test dispose
 24          imageIcon.addMouseListener(new MouseAdapter() {
 25              @Override
 26              public void mouseDoubleClicked(final IMouseButtonEvent mouseEvent) {
 27                  imageIcon.dispose();
 28                  container.layoutLater();
 29              }
 30          });
 31  
 32          //dispose the image if it was removed from its container
 33          imageIcon.addDisposeListener(new IDisposeListener() {
 34              @Override
 35              public void onDispose() {
 36                  image.dispose();
 37                  //CHECKSTYLE:OFF
 38                  System.out.println("DISPOSED IMAGE");
 39                  //CHECKSTYLE:ON
 40              }
 41          });
 42  
 43          //set the root frame visible
 44          frame.setVisible(true);
 45      }
 46  }

Das image wird auf einem Icon Widget gesetzt (Zeile 21). Auf dem Icon Widget wird ein Listener registriert, welcher dieses bei einem Doppeklick aus seinem Container entfernt, wodurch es disposed wird.

In Zeile 16 bis 18 könnte man zum Beispiel auch das Folgende schreiben, um das Image aus einem File einzulesen:

  1      //create a image from file
  2      final String path = "C:/projects/jo-widgets/trunk/docu/images/widgets_hierarchy_1.gif";
  3      final IImage image = ImageFactory.createImage(new File(path));
Das ImageCanvasSnipped

Das ImageCanvasSnipped zeigt die Verwendung eines Images in Verbindung mit einem Canvas:

  1  public final class ImageCanvasSnipped implements IApplication {
  2  
  3      @Override
  4      public void start(final IApplicationLifecycle lifecycle) {
  5  
  6          //create the root frame
  7          final IFrame frame = Toolkit.createRootFrame(BPF.frame("Image Canvas Snipped"), lifecycle);
  8          frame.setLayout(FillLayout.get());
  9  
 10          //create a scroll composite
 11          final IScrollComposite container = frame.add(BPF.scrollComposite());
 12          container.setLayout(FillLayout.get());
 13  
 14          //create a image from url
 15          final String url = "http://www.jowidgets.org/docu/images/widgets_hierarchy_1.gif";
 16          final IImage image = ImageFactory.createImage(UrlFactory.create(url));
 17  
 18          //use a canvas to display the image
 19          final ICanvas canvas = container.add(BPF.canvas());
 20  
 21          //set the preferred size of the canvas to the image size
 22          canvas.setPreferredSize(image.getSize());
 23  
 24          //add a paint listener to draw the image and an arrow
 25          canvas.addPaintListener(new IPaintListener() {
 26              @Override
 27              public void paint(final IPaintEvent event) {
 28                  final IGraphicContext gc = event.getGraphicContext();
 29  
 30                  //draw the image
 31                  gc.drawImage(image);
 32  
 33                  //draw with green color
 34                  gc.setForegroundColor(Colors.GREEN);
 35  
 36                  //define a polygon that shapes an arrow
 37                  final Point p1 = new Point(438, 205);
 38                  final Point p2 = new Point(464, 205);
 39                  final Point p3 = new Point(464, 199);
 40                  final Point p4 = new Point(486, 211);
 41                  final Point p5 = new Point(464, 223);
 42                  final Point p6 = new Point(464, 217);
 43                  final Point p7 = new Point(438, 217);
 44                  final Point[] polygon = new Point[] {p1, p2, p3, p4, p5, p6, p7, p1};
 45  
 46                  //fill the polygon 
 47                  gc.fillPolygon(polygon);
 48              }
 49          });
 50  
 51          //set the root frame visible
 52          frame.setVisible(true);
 53      }
 54  }

Das Image wird mit Hilfe eine Canvas gezeichnet (Zeile 31). Anschließend wird auf der Grafik ein grüner Pfeil, welcher durch ein Polygon definiert wird, gezeichnet (Zeile 47). Die folgende Abbildung zeigt das Ergebnis:

Abbildung 43. ImageCanvasSnipped

ImageCanvasSnipped

Das BufferedImageSnipped

Das BufferedImageSnipped zeigt die Verwendung eines Buffered Image:

  1  public final class BufferedImageSnipped implements IApplication {
  2  
  3      @Override
  4      public void start(final IApplicationLifecycle lifecycle) {
  5  
  6          //create the root frame
  7          final IFrameBluePrint frameBp = BPF.frame("Buffered Image Snipped");
  8          final IFrame frame = Toolkit.createRootFrame(frameBp, lifecycle);
  9          frame.setSize(300, 200);
 10          frame.setBackgroundColor(Colors.WHITE);
 11          frame.setLayout(FillLayout.builder().margin(10).build());
 12  
 13          //create a arrow buffered image
 14          final IBufferedImage image = createArrowImage();
 15  
 16          //create a label using the buffered image as icon
 17          frame.add(BPF.label().setIcon(image).setText("Hello world"));
 18  
 19          //set the root frame visible
 20          frame.setVisible(true);
 21      }
 22  
 23      private static IBufferedImage createArrowImage() {
 24          //create a buffered image
 25          final IBufferedImage image = ImageFactory.createBufferedImage(52, 26);
 26          final IGraphicContext gc = image.getGraphicContext();
 27  
 28          //use anti aliasing
 29          gc.setAntiAliasing(AntiAliasing.ON);
 30  
 31          //define a polygon that shapes an arrow
 32          final Point p1 = new Point(0, 6);
 33          final Point p2 = new Point(26, 6);
 34          final Point p3 = new Point(26, 0);
 35          final Point p4 = new Point(48, 12);
 36          final Point p5 = new Point(26, 24);
 37          final Point p6 = new Point(26, 18);
 38          final Point p7 = new Point(0, 18);
 39          final Point[] polygon = new Point[] {p1, p2, p3, p4, p5, p6, p7, p1};
 40  
 41          //use white background for the image
 42          gc.setBackgroundColor(Colors.WHITE);
 43          gc.clear();
 44  
 45          //draw with green color
 46          gc.setForegroundColor(Colors.GREEN);
 47  
 48          //fill the polygon 
 49          gc.fillPolygon(polygon);
 50  
 51          return image;
 52      }
 53  }

Die folgende Abbildung zeigt das Ergebnis:

Abbildung 44. BufferedImageSnipped

BufferedImageSnipped



[25] Hier macht es sich besonders unangenehm bemerkbar, dass der Name IImageConstant und nicht IImageKey gewählt wurde, da ein IImage nicht zwingend eine Konstante sein muss und das dispose() explizit zum Vertrag gehört.


Siehe auch PDF Version dieses Dokuments, Jowidgets API Spezifikation