Titel | Inhalt | Suchen | Index | API | Go To Java 2, Zweite Auflage, Handbuch der Java-Programmierung |
<< | < | > | >> | Kapitel 34 - Bitmaps und Animationen |
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:
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. |
|
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"); |
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. Weitere Varianten von drawImage, die ein Bild sogar skalieren und spiegeln können, werden in der API-Dokumentation beschrieben. |
|
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 } |
Die Ausgabe des Programms ist:
Abbildung 34.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. |
|
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 /* Listing3403.java */ 002 003 import java.awt.*; 004 import java.awt.event.*; 005 006 public class Listing3403 007 extends Frame 008 { 009 private Image img; 010 011 public static void main(String[] args) 012 { 013 Listing3403 wnd = new Listing3403(); 014 } 015 016 public Listing3403() 017 { 018 super("Bitmap"); 019 setBackground(Color.lightGray); 020 setSize(250,150); 021 setVisible(true); 022 //WindowListener 023 addWindowListener(new WindowClosingAdapter(true)); 024 //Bild laden 025 img = getToolkit().getImage("duke.gif"); 026 MediaTracker mt = new MediaTracker(this); 027 mt.addImage(img, 0); 028 try { 029 //Warten, bis das Image vollständig geladen ist, 030 mt.waitForAll(); 031 } catch (InterruptedException e) { 032 //nothing 033 } 034 repaint(); 035 } 036 037 public void paint(Graphics g) 038 { 039 if (img != null) { 040 g.drawImage(img,40,40,this); 041 } 042 } 043 } |
Listing3403.java |
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 |
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. |
|
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 /* Listing3405.java */ 002 003 import java.awt.*; 004 import java.awt.event.*; 005 006 public class Listing3405 007 extends Frame 008 { 009 public static void main(String[] args) 010 { 011 Listing3405 wnd = new Listing3405(); 012 } 013 014 public Listing3405() 015 { 016 super("Bitmap-Komponente"); 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(new WindowClosingAdapter(true)); 029 } 030 } |
Listing3405.java |
Die Ausgabe des Programms ist:
Abbildung 34.2: Verwendung von BitmapComponent
Titel | Inhalt | Suchen | Index | API | Go To Java 2, Zweite Auflage, Addison Wesley, Version 2.0 |
<< | < | > | >> | © 2000 Guido Krüger, http://www.gkrueger.com |