Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 

24.1 Bitmaps



24.1.1 Laden und Anzeigen einer Bitmap

Das Anzeigen einer Bitmap kann in zwei Schritte unterteilt werden:

Das Laden erfolgt mit der Methode getImage, die eine Instanz der Klasse Image zurückgibt. Das Image-Objekt kann dann mit der Methode drawImage der Klasse Graphics angezeigt werden.

getImage gibt es in verschiedenen Varianten, die sich dadurch unterscheiden, aus welcher Quelle sie die Bitmap-Daten laden. In einer Java-Applikation wird in der Regel die Methode getImage aus der Klasse Toolkit verwendet. Sie erwartet den Namen einer lokalen Datei als Parameter:

public Image getImage(String filename)
java.awt.Toolkit

getImage versteht in der aktuellen Version des AWT die beiden Bitmap-Typen gif und jpeg. Andere Grafikformate, wie etwa das unter Windows gebräuchliche bmp-Format, werden nicht unterstützt, sondern müssen bei Bedarf konvertiert werden.

Neben den getImage-Methoden gibt es seit dem JDK 1.2 auch zwei Methoden mit dem Namen createImage in der Klasse Toolkit:

public abstract Image createImage(String filename)

public abstract Image createImage(URL url)
java.awt.Toolkit

Sie laden ein Image bei jeder Verwendung neu und führen (im Gegensatz zu getImage) kein Caching des Bildes durch. Die JDK-Dokumentation empfiehlt sie gegenüber getImage, weil bei deren Verwendung Speicherlecks durch das unbegrenzte Zwischenspeichern der Bilddaten entstehen können.

 JDK1.1/1.2 

Das Toolkit für die aktuelle Umgebung kann mit der Methode getToolkit der Klasse Component beschafft werden:

public Toolkit getToolkit()
java.awt.Component

Der gesamte Code zum Laden einer Bitmap duke.gif sieht daher so aus:

001 Image img;
002 img = getToolkit().getImage("duke.gif");
Listing 24.1: Laden einer Bitmap-Datei

Um das Image anzuzeigen, kann die Methode drawImage der Klasse Graphics aufgerufen werden:

public boolean drawImage(
   Image img, int x, int y, ImageObserver observer
)
java.awt.Graphics

drawImage gibt es in unterschiedlichen Ausprägungen. Die hier vorgestellte Variante erwartet das anzuzeigende Image-Objekt und die Position (x,y), an der die linke obere Ecke der Bitmap plaziert werden soll. Das zusätzlich angegebene Objekt observer dient zur Übergabe eines ImageObserver-Objektes, mit dem der Ladezustand der Bitmaps überwacht werden kann. Hier kann der this-Zeiger, also eine Referenz auf das Fensterobjekt, übergeben werden. Eine weitere Variante von drawImage, die ein Bild sogar skalieren und spiegeln kann, wurde in Kapitel 2 vorgestellt. Wir wollen hier nicht weiter auf Details eingehen.

 Hinweis 

Das folgende Listing ist ein einfaches Beispiel für das Laden und Anzeigen der Bitmap duke.gif. Alle erforderlichen Aktionen erfolgen innerhalb von paint:

001 public void paint(Graphics g)
002 {
003    Image img;
004    img = getToolkit().getImage("duke.gif");
005    g.drawImage(img,40,40,this);
006 }
Listing 24.2: Laden und Anzeigen einer Bitmap

 Beispiel 

Die Ausgabe des Programms ist:

Abbildung 24.1: Laden und Anzeigen einer Bitmap

Die gewählte Vorgehensweise ist nicht besonders effizient, denn die Bitmap wird bei jedem Aufruf von paint neu geladen. Besser ist es, die benötigten Bitmaps einmal zu laden und dann im Speicher zu halten. Obwohl man vermuten könnte, daß dies die Ladezeit des Fensters unannehmbar verlängern würde, ist der Konstruktor der Klasse eine gute Stelle dafür. Der Aufruf von getImage lädt die Bitmap nämlich noch nicht, sondern bereitet das Laden nur vor. Der eigentliche Ladevorgang erfolgt erst, wenn die Bitmap beim Aufruf von drawImage tatsächlich benötigt wird.

 Tip 

Die Klasse MediaTracker

Manchmal kann es sinnvoll sein, den tatsächlichen Ladevorgang des Bildes abzuwarten, bevor im Programm fortgefahren wird. Wird zum Beispiel die Größe der Bitmap benötigt, um sie korrekt auf dem Bildschirm anordnen oder skalieren zu können, muß das Programm warten, bis das Image vollständig erzeugt ist.

Für diese Zwecke steht die Klasse MediaTracker zur Verfügung, die das Laden eines oder mehrerer Bilder überwacht. Dazu wird zunächst eine Instanz der Klasse angelegt:

public MediaTracker(Component comp)
java.awt.MediaTracker

Als Komponente wird der this-Zeiger des aktuellen Fensters übergeben. Anschließend werden durch Aufruf von addImage alle Bilder, deren Ladevorgang überwacht werden soll, an den MediaTracker übergeben:

public void addImage(Image img, int id)
java.awt.MediaTracker

Der zusätzlich übergebene Parameter id kann dazu verwendet werden, einen Namen zu vergeben, unter dem auf das Image zugegriffen werden kann. Zusätzlich bestimmt er die Reihenfolge, in der die Images geladen werden. Bitmaps mit kleineren Werten werden zuerst geladen.

Der MediaTracker bietet eine Reihe von Methoden, um den Ladezustand der Bilder zu überwachen. Wir wollen hier nur die Methode waitForAll betrachten. Sie wartet, bis alle Images vollständig geladen sind:

public void waitForAll()
  throws InterruptedException
java.awt.MediaTracker

Nach Abschluß des Ladevorgangs sendet waitForAll eine Ausnahme des Typs InterruptedException.

Das vollständige Beispielprogramm zur Anzeige von duke.gif sieht nun so aus:

001 /* Listing2403.java */
002 
003 import java.awt.*;
004 import java.awt.event.*;
005 
006 public class Listing2403
007 extends Frame
008 {
009    private Image img;
010 
011    public static void main(String[] args)
012    {
013       Listing2403 wnd = new Listing2403();
014    }
015 
016    public Listing2403()
017    {
018       super("Listing2403");
019       setBackground(Color.lightGray);
020       setSize(250,150);
021       setVisible(true);
022       //WindowListener
023       addWindowListener(
024          new WindowAdapter() {
025             public void windowClosing(WindowEvent event)
026             {
027                System.exit(0);
028             }
029          }
030       );
031       //Bild laden
032       img = getToolkit().getImage("duke.gif");
033       MediaTracker mt = new MediaTracker(this);
034       mt.addImage(img, 0);
035       try {
036          //Warten, bis das Image vollständig geladen ist,
037          mt.waitForAll();
038       } catch (InterruptedException e) {
039          //nothing
040       }
041 	  repaint();
042    }
043 
044    public void paint(Graphics g)
045    {
046       if (img != null) {
047          g.drawImage(img,40,40,this);
048       }
049    }
050 }
Listing2403.java
Listing 24.3: Programm zum Laden und Anzeigen einer Bitmap

 Beispiel 

24.1.2 Entwicklung einer eigenen Bitmap-Komponente

Ein schönes Beispiel für die Verwendung von Bitmaps ist die Konstruktion einer Komponente BitmapComponent, die in Dialogboxen zur Anzeige von Bitmaps verwendet werden kann. Die Verwendung soll dabei so einfach wie möglich sein, d.h., außer der Übergabe des Dateinamens an den Konstruktor soll kein zusätzlicher Aufwand entstehen.

Zur Konstruktion der Komponente gehen wir in folgenden Schritten vor:

Nach diesen Ausführungen ist die Implementierung einfach:

001 /* BitmapComponent.java */
002 
003 import java.awt.*;
004 
005 class BitmapComponent
006 extends Canvas
007 {
008    private Image img;
009 
010    public BitmapComponent(String fname)
011    {
012       img = getToolkit().getImage(fname);
013       MediaTracker mt = new MediaTracker(this);
014 
015       mt.addImage(img, 0);
016       try {
017          //Warten, bis das Image vollständig geladen ist,
018          //damit getWidth() und getHeight() funktionieren
019          mt.waitForAll();
020       } catch (InterruptedException e) {
021          //nothing
022       }
023    }
024 
025    public void paint(Graphics g)
026    {
027       g.drawImage(img,1,1,this);
028    }
029 
030    public Dimension getPreferredSize()
031    {
032       return new Dimension(
033          img.getWidth(this),
034          img.getHeight(this)
035       );
036    }
037 
038    public Dimension getMinimumSize()
039    {
040       return new Dimension(
041          img.getWidth(this),
042          img.getHeight(this)
043       );
044    }
045 }
BitmapComponent.java
Listing 24.4: Eine Komponente zum Anzeigen einer Bitmap

Bei diesem Beispiel ist die Verwendung des MediaTrackers obligatorisch. Andernfalls könnte es passieren, daß zum Zeitpunkt des Aufrufs von getPreferredSize oder getMinimumSize die Bitmap noch nicht geladen ist und die Methoden getWidth und getHeight 0 zurückgeben. Dies würde dann dazu führen, daß der Layoutmanager den benötigten Platz fehlerhaft berechnet und die Komponente falsch oder gar nicht angezeigt wird.

 Warnung 

Die Einbindung von BitmapComponent in einen Dialog erfolgt analog zur Einbindung jeder anderen Komponente durch Aufruf der Methode add der Klasse Component. Das folgende Listing gibt ein Beispiel für die Einbindung der neuen Komponente:

001 /* Listing2405.java */
002 
003 import java.awt.*;
004 import java.awt.event.*;
005 
006 public class Listing2405
007 extends Frame
008 {
009    public static void main(String[] args)
010    {
011       Listing2405 wnd = new Listing2405();
012    }
013 
014    public Listing2405()
015    {
016       super("Listing2405");
017       setBackground(Color.lightGray);
018       setSize(250,150);
019       setVisible(true);
020       //Hinzufügen der Komponenten
021       setLayout(new GridLayout(2,2));
022       add(new BitmapComponent("duke.gif"));
023       add(new BitmapComponent("duke.gif"));
024       add(new BitmapComponent("duke.gif"));
025       add(new BitmapComponent("duke.gif"));
026       pack();
027       //WindowListener
028       addWindowListener(
029          new WindowAdapter() {
030             public void windowClosing(WindowEvent event)
031             {
032                System.exit(0);
033             }
034          }
035       );
036    }
037 }
Listing2405.java
Listing 24.5: Verwenden der Bitmap-Komponente

 Beispiel 

Die Ausgabe des Programms ist:

Abbildung 24.2: Verwendung von BitmapComponent


 Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 
Go To Java 2, Addison Wesley, Version 1.0.2, © 1999 Guido Krüger, http://www.gkrueger.com