Home > Informatik > Informatik EF > Folge 5

5.3 Workshop "Kreise"

In diesem Workshop geht es weniger um das Zeichnen von Kreisen in einer Java-Anwendung, als vielmehr um die Frage, wie man Graphik-Befehle bündeln und in eigene Klassen außerhalb der Anwendung auslagern kann. Dabei werden wir wieder ganz langsam Schritt für Schritt vorgehen, so dass möglichst viele Benutzer dieser Seite auch folgen können. Wir beginnen erst mal ganz "harmlos" und lassen ein paar Kreise in eine Java-Anwendung zeichnen. Das haben wir ja bereits in dem Abschnitt "Kreise" der Folge 5.1 gemacht.

 

Schritt 1 - Eine Anwendung mit mehreren Kreisen erstellen

Starten Sie BlueJ und legen Sie ein neues Projekt an mit einer Klasse an. Entfernen Sie den Quelltext aus dieser Klasse und kopieren Sie den Minimal-Quelltext einer Java-Anwendung in die leere Klasse hinein. Ersetzen Sie dann den Quelltext der paint-Methode durch diesen Quelltext:

    public void paint(Graphics g)
    {
        g.setColor(new Color(221,127,63));
        g.fillOval(50,50,100,100);
        g.setColor(Color.BLACK);
        g.drawOval(50,50,100,100);
        g.setColor(new Color(127,221,63));
        g.fillOval(150,150,70,70);
        g.setColor(Color.BLACK);
        g.drawOval(150,150,70,70);     
        g.setColor(new Color(255,127,127));
        g.fillOval(250,250,50,50);
        g.setColor(Color.BLACK);
        g.drawOval(250,250,50,50);            
    }

Wenn Sie die Klasse kompilieren und dann die main-Methode starten, sollte folgendes zu sehen sein:

Drei bunte Kreise in einer Reihe, die von links oben nach rechts unten geht. Dabei werden die Kreise immer kleiner. Die drei Kreise haben unterschiedliche Pastellfarben.

Schritt 3 - Auslagern in eine Methode

Wenn wir uns den Quelltext der paint-Methode näher ansehen, fällt auf, dass im Grunde dreimal die gleichen vier Befehle ausgeführt werden:

  1. Eine Farbe für den Kreis wählen
  2. Den Inhalt des Kreises in dieser Farbe zeichnen
  3. Die Farbe Schwarz wählen
  4. Die Umrandung des Kreises zeichnen

Wenn man ein Programm analysiert und dabei feststellt, dass bestimmte Befehle immer wieder wiederholt werden, dann ist es üblich, diese Befehle in eine eigene Methode auszulagern. Genau das machen wir jetzt:

    public void drawCircle(Graphics g, int x, int y, int rad, Color c)
    {
       g.setColor(c);
       g.fillOval(x,y,rad*2,rad*2);
       g.setColor(Color.BLACK);
       g.drawOval(x,y,rad*2,rad*2);       
    }
    
    public void paint(Graphics g)
    {
        drawCircle(g, 50, 50, 50,new Color(221,127, 63));
        drawCircle(g,150,150, 35,new Color(127,221, 63));
        drawCircle(g,250,250, 25,new Color(255,127,127));    
    }

Die Methode drawCircle, die wir gerade geschrieben haben, übernimmt das Zeichnen eines Kreises, sie führt die oben genannten vier Befehle aus. Die paint-Methode hat sich damit drastisch verkürzt, da nur noch die Methode drawCircle dreimal aufgerufen werden muss. Zugegeben, durch die lange Parameterliste geht etwas an Übersichtlichkeit verloren. Aber dafür haben wir das Zeichnen des Kreises auf eine Stelle im Quelltext konzentriert.

Vorteile der Auslagerung

Stellen Sie sich vor, der Rand der Kreise soll nicht eine Breite von 1 Pixel haben, sondern von 2 Pixeln. In dem "alten" Quelltext müssten Sie jetzt an drei Stellen der paint-Methode den entsprechenden neuen Befehl einbauen. Da wir aber das Zeichnen der Kreise in eine eigene Methode ausgelagert haben, müssen wir nur noch diese Methode verändern; eine zusätzliche Zeile oder eine veränderte Anweisung genügt hier vollkommen.

Schritt 4 - Auslagerung in eine eigene Klasse

Betrachten Sie folgenden Quelltext der veränderten Java-Anwendung:

import java.awt.*;
import javax.swing.*;

public class Anmwendung1 extends JFrame
{
    Circle kreis1, kreis2, kreis3;
    
    public Anmwendung1()
    {
        kreis1 = new Circle(50, 50, 50,new Color(221,127, 63));
        kreis2 = new Circle(150,150, 35,new Color(127,221, 63));
        kreis3 = new Circle(250,250, 25,new Color(255,127,127));
        
        setSize(500,500);
        setTitle("Workshop 'Kreise'");
        setResizable(false);
        setVisible(true);
    }

    public void paint(Graphics g)
    {
        kreis1.paint(g);
        kreis2.paint(g);
        kreis3.paint(g);
    }

    public static void main(String[] args) 
    {
        new Anmwendung1();
    }
}

Was ist hier neu? Am Anfang werden drei Objekte einer Klasse Kreis deklariert:

Circle kreis1, kreis2, kreis3;

Um die Klasse Circle kümmern wir uns gleich. Zunächst mal weiter mit der Java-Anwendung.

Im Konstruktor der Anwendung werden die drei Circle-Objekte initialisiert; es wird also für jedes Objekt der Konstruktor der Klasse Circle aufgerufen. Dieser Konstruktor erwartet vier Parameter:.

  1. X-Position des Kreismittelpunktes
  2. Y-Position des Kreismittelpunktes
  3. Radius des Kreises
  4. Farbe des Kreises

Das sind genau die gleichen Parameter, wie wir sie bei der internen Methode drawCircle verwendet haben, in Schritt 3. Lediglich der Graphics-Parameter g fehlt hier.

Nach der Initialisierung der drei Circle-Objekte wird das Fenster selbst initialisiert, wie üblich wird die Größe bestimmt, der Titel und so weiter.

In der paint-Methode werden die drei Kreise nun gezeichnet. Das geschieht nach dem Prinzip der Delegation. Die Klasse Circle stellt offensichtlich eine eigene paint-Methode zur Verfügung, die jetzt einfach aufgerufen werden kann. Dazu muss das Graphics-Objekt g an die Circle-Methode paint übergeben werden.

Die Klasse Circle

Betrachten wir nun die neue Klasse Circle, die wir selbst schreiben müssen, weil sie von Java nicht zur Verfügung gestellt wird:

import java.awt.*;

public class Circle
{
    int x, y, rad;
    Color c;
    
    public Circle(int xPos, int yPos, int radius, Color color)
    {
        x   = xPos;
        y   = yPos;
        rad = radius;
        c   = color;
    }
    
    public void paint(Graphics g)
    {
       g.setColor(c);
       g.fillOval(x,y,rad*2,rad*2);
       g.setColor(Color.BLACK);
       g.drawOval(x,y,rad*2,rad*2);    
    }

}

Die Eigenschaften eines Kreises werden in Form von vier Attributen verwaltet:

  1. x = X-Position des Kreismittelpunktes
  2. y = Y-Position des Kreismittelpunktes
  3. rad = Radius des Kreises
  4. c = Farbe des Kreises

Der Konstruktor der neuen Klasse nimmt die Werte dieser vier Attribute als Parameter entgegen und weist die Parameter-Werte dann den Attributen zu.

Die paint-Methode der Klasse Circle benötigt einen Parameter der Klasse Graphics, damit sie in die Java-Anwendung zeichnen kann. Ansonsten wird der Kreis genau so gezeichnet wie bisher: Zuerst das farbige Innere, dann der schwarze Rand.

Der import-Befehl ganz zu Beginn des Quelltextes ist nötig, damit die Klasse Graphics mit ihren Methoden zur Verfügung steht.