Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage
<< | < | > | >> | API | Kapitel 23 - Grafikausgabe

## 23.4 Weiterführende Funktionen

- 23.4 Weiterführende Funktionen
  - 23.4.1 Linien- oder Füllmodus
  - 23.4.2 Kopieren und Löschen von Flächen
  - 23.4.3 Die Clipping-Region

### 23.4.1 Linien- oder Füllmodus

Mit Ausnahme von `drawLine` können alle vorgestellten Routinen entweder im Linien- oder im Füllmodus verwendet werden. Beginnt der Methodenname mit `draw`, erfolgt die Ausgabe im Linienmodus. Es wird lediglich der Umriß der jeweiligen Figur gezeichnet. Beginnt der Methodenname mit `fill`, erfolgt die Ausgabe im Füllmodus, und das Objekt wird mit ausgefüllter Fläche gezeichnet.

Nachfolgend noch einmal eine Zusammenstellung der verfügbaren Füllfunktionen:

    public void fillRect(int x, int y, int w, int h)

    public void fillRoundRect(
       int x, int y, int w, int h, int xr, int yr
    )

    public void fillPolygon(int[] arx, int[] ary, int cnt)
    public void fillPolygon(Polygon p)

    public void fillOval(int x, int y, int width, int height)

    public void fillArc(
       int x, int y, int width, int height,
       int startAngle, int arcAngle
    )
| java.awt.Graphics

Das nachfolgende Beispiel verwendet die Methoden `fillRect`, `fillPolygon`, `fillOval` und `fillArc`, um einen stilisierten »Java«-Schriftzug anzuzeigen:

    001 /* GefuellteFlaechen.inc */
    002
    003 public void paint(Graphics g)
    004 {
    005   int[] arx = {150,175,200,150};
    006   int[] ary = {100,150,100,100};
    007
    008   //---J
    009   g.fillRect(70,40,20,80);
    010   g.fillArc(30,90,60,60,225,180);
    011   //---a
    012   g.fillOval(100,100,40,50);
    013   g.fillRect(120,100,20,50);
    014   //---v
    015   g.fillPolygon(arx,ary,arx.length);
    016   //---a
    017   g.fillOval(210,100,40,50);
    018   g.fillRect(230,100,20,50);
    019 }
| GefuellteFlaechen.inc

Listing 23.10: Ausgabe von gefüllten Flächen

Abbildung 23.8: Ausgabe von gefüllten Flächen

|  |  |  | Man kann sich die Wirkungsweise der verschiedenen Methodenaufrufe etwas deutlicher machen, wenn man sie nicht im Füll-, sondern im Linienmodus arbeiten läßt. Dies ist auch eine nützliche Vorgehensweise beim Erstellen von komplexeren Grafiken. In unserem Beispiel würde die Ausgabe des Programms dann so aussehen: |  |
Tip

Abbildung 23.9: Ausgabe des Java-Logos als Liniengrafik

### 23.4.2 Kopieren und Löschen von Flächen

Die Klasse `Graphics` stellt auch einige Methoden zum Bearbeiten bereits gezeichneter Flächen zur Verfügung. Diese erlauben es beispielsweise, einen rechteckigen Ausschnitt des Ausgabefensters zu löschen oder zu kopieren:

    public void clearRect(
       int x, int y,
       int width, int height
    )

    public void copyArea(
       int x, int y,
       int width, int height,
       int dx, int dy
    )
| java.awt.Graphics

Die Methode `clearRect` löscht das angegebene Rechteck, indem sie den Bereich mit der aktuellen Hintergrundfarbe ausfüllt. `(x,y)` bezeichnet die linke obere Ecke, `(width,height)` die Breite und Höhe des Fensters.

Soll ein Teil des Fensters kopiert werden, kann dazu die Methode `copyArea` verwendet werden. Die ersten vier Parameter bezeichnen in der üblichen Weise den zu kopierenden Ausschnitt. `(dx,dy)` gibt die Entfernung des Zielrechtecks in x- und y-Richtung an. `copyArea` kopiert das ausgewählte Rechteck also immer an die Position `(x+dx,` `y+dy)`.

Das folgende Beispiel demonstriert die Anwendung von `copyArea` anhand eines Programms, das den Bildschirm (ähnlich dem Windows 95-Hintergrund »Labyrinth«) mit einem Muster füllt:

    001 /* Kopieren.inc */
    002
    003 public void paint(Graphics g)
    004 {
    005   int xorg = 4;
    006   int yorg = 28;
    007   int[] arx = {0,6,6,2,2,4,4,0,0};
    008   int[] ary = {0,0,6,6,4,4,2,2,8};
    009   for (int i = 0; i < arx.length; ++i) {
    010     arx[i] += xorg;
    011     ary[i] += yorg;
    012   }
    013   g.drawPolyline(arx,ary,arx.length);
    014   for (int x = 0; x <= 300; x += 8) {
    015     for (int y = 0; y <= 160; y += 8) {
    016       if (x != 0 || y != 0) {
    017         g.copyArea(xorg,yorg,8,8,x,y);
    018       }
    019     }
    020   }
    021 }
| Kopieren.inc

Listing 23.11: Kopieren von Flächen mit copyArea

Hier wird zunächst ein einziges Exemplar des Musters in der Größe 8*8 Pixel in der linken oberen Ecke des Fensters gezeichnet. Alle weiteren Wiederholungen werden durch Kopieren hergestellt:

Abbildung 23.10: Kopieren von Grafiken

|  |  |  | Wann die Anwendung der Methode `copyArea` in der Praxis sinnvoll ist, muß von Fall zu Fall entschieden werden. In unserem Beispiel wäre es sehr einfach gewesen, das Fenster auch ohne Kopieren mit dem Muster zu füllen, und der Overhead der Kopiermethode hätte vermieden werden können. Ist es dagegen sehr aufwendig, einen Teil des Fensters zu zeichnen, der an anderer Stelle repliziert werden soll, ist die Anwendung von `copyArea` sinnvoll. |  |
Tip

### 23.4.3 Die Clipping-Region

Jeder Grafikkontext hat eine zugeordnete Clipping-Region, die dazu dient, die Ausgabe auf einen bestimmten Bereich einzugrenzen. So wird beispielsweise verhindert, daß wichtige Teile eines Fensters, wie z.B. der Rahmen oder die Menüzeile, von den Ausgabeoperationen des Programms überschrieben werden.

Auch in Java besitzt ein Fenster eine Clipping-Region, die an das übergebene `Graphics`-Objekt gebunden ist. Beim Aufruf der `paint`-Methode entspricht ihre Größe der zur Ausgabe zur Verfügung stehenden Fläche. Mit Hilfe der Methode `clipRect` kann die Clipping-Region nun sukzessive verkleinert werden:

    public void clipRect(int x, int y, int width, int height)
| java.awt.Graphics

|  | Ein Aufruf dieser Methode begrenzt die Clipping-Region auf die Schnittmenge zwischen dem angegebenen Rechteck und ihrer vorherigen Größe. Da eine Schnittmenge niemals größer werden kann als eine der Mengen, aus denen sie gebildet wurde, kann `clipRect` also lediglich dazu verwendet werden, die Clipping-Region zu verkleinern. |  |
Hinweis

Soll die Clipping-Region auf einen beliebigen Bereich innerhalb des aktuellen Fensters ausgedehnt werden (der dabei auch größer sein kann als die bisherige Clipping-Region), so kann dazu die Methode `setClip` verwendet werden, die in zwei verschiedenen Ausprägungen zur Verfügung steht:

    public abstract void setClip(int x, int y, int width, int height)
    public abstract void setClip(Shape clip)
| java.awt.Graphics

Die erste Version übergibt ein Rechteck, das die Größe der gewünschten Clipping-Region in Client-Koordinaten angibt. Die zweite Variante erlaubt die Übergabe eines Objekts, welches das `Shape`-Interface implementiert. Das Interface besitzt derzeit jedoch nur die Methode `getBounds`, mit der das umschließende Rechteck ermittelt werden kann:

    public abstract Rectangle getBounds()
| java.awt.Shape

Da außer Rechtecken derzeit keine anders geformten `Shape`-Objekte zur Definition der Clipping-Region unterstützt werden, wollen wir hier nicht weiter auf die zweite Variante von `setClip` eingehen.

Soll die Ausdehnung der aktuellen Clipping-Region ermittelt werden, so kann dazu eine der Methoden `getClip` oder `getClipBounds` verwendet werden:

    public abstract Shape getClip()

    public abstract Rectangle getClipBounds()
| java.awt.Graphics

Dabei liefert `getClip` ein `Shape`-Objekt, das derzeit denselben Einschränkungen unterliegt wie das beim Aufruf von `setClip` übergebene. `getClipBounds` liefert das kleinste Rechteck, das die aktuelle Clipping-Region vollständig umschließt.

Das folgende Beispiel wiederholt die Ausgabe des Java-Logos, grenzt aber vorher die Clipping-Region auf ein Fenster der Größe 150*80 Pixel ein, das seinen Ursprung an Position (50,50) hat:

    001 /* Clipping.inc */
    002
    003 public void paint(Graphics g)
    004 {
    005   int[] arx = {150,175,200,150};
    006   int[] ary = {100,150,100,100};
    007
    008   g.setClip(50,50,150,80);
    009   //---J
    010   g.fillRect(70,40,20,80);
    011   g.fillArc(30,90,60,60,225,180);
    012   //---a
    013   g.fillOval(100,100,40,50);
    014   g.fillRect(120,100,20,50);
    015   //---v
    016   g.fillPolygon(arx,ary,arx.length);
    017   //---a
    018   g.fillOval(210,100,40,50);
    019   g.fillRect(230,100,20,50);
    020 }
| Clipping.inc

Listing 23.12: Verwendung der Clipping-Funktionen

Die Ausgabe des Programms erfolgt nun nur noch innerhalb der Clipping-Region:

Abbildung 23.11: Verwendung der Clipping-Funktionen

Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage, Addison Wesley, Version 3.0
<< | < | > | >> | API | © 1998-2002 Guido Krüger, http://www.javabuch.de