Home > Informatik > Informatik EF > Folge 5

5.1 - Java-Anwendungen

Bisher haben wir recht einfache Anwendungen geschrieben, die Ausgabe der Ergebnisse erfolgte immer in der Konsole, und die Eingabe von Werten wie Gewicht, Körpergröße, Benzinverbrauch etc. erfolgte mit Hilfe von Parametern, die dann beim Aufruf der Methoden über BlueJ-Dialogboxen abgefragt wurden.

In dieser Folge und in der nächsten Folge wollen wir aber "richtige" Java-Anwendungen erstellen, also Programme mit einer graphischen Benutzeroberfläche wie Editboxen, Buttons und so weiter, und wir wollen die wichtigsten Zeichenbefehle von Java kennenlernen, mit denen wir dann eindrucksvolle Graphiken erstellen können. Ganz nebenbei erweitern Sie dann auch Ihre Kenntnisse über den Umgang mir for-Schleifen.

Lernziele

Wenn Sie diese Seite durchgearbeitet haben, sollten Sie wissen

  • wie man eine minimale "richtige" Java-Anwendung mit einer main()-Methode erstellt
  • wie man einfache Zeichnungen anfertigt, die in der Anwendung erscheinen.

Schritt 1 - Neues Projekt

Vorbemerkung

Es ist nicht das Ziel des Informatik-Unterrichts der Sek. II, Ihnen das Programmieren von komplexen Java-Anwendungen beizubringen. Selbst in den ersten Semestern des Informatik-Studiums arbeitet man weitgehend noch mit einfachen Konsolen-Anwendungen. Daher werden wir hier eine KI nutzen, um uns eine minimale Java-Anwendung erstellen zu lassen, mit der wir dann weiterarbeiten können.

⇒ Starten Sie BlueJ und legen Sie ein neues Projekt an. Klicken Sie dann auf Neue Klasse und achten Sie darauf, dass in dem Dialogfenster Neue Klasse erzeugen der Klassentyp Klasse ausgewählt ist.

In unserem Beispiel hat die Klasse den Namen "Anwendung1".

Schritt 2 - Eine Minimal-Anwendung

⇒ Öffnen Sie die Klasse Anwendung1 durch einen Doppelklick und entfernen Sie den gesamten Quelltext. Kopieren Sie dann folgenden Quelltext in die Zwischenablage und fügen Sie ihn in das leere Editorfenster ein:

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

public class Zeichenfenster extends JPanel
{
   @Override
   protected void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      g.drawString("Hallo Welt", 200, 250);
   }

   public static void main(String[] args)
   {
      JFrame frame = new JFrame("Zeichenfenster");

      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(500, 500);
      frame.setResizable(false);
      frame.add(new Zeichenfenster());
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }
}

Dieser Quelltext wurde von Mistral Vibe erzeugt nach der Aufforderung: "Erzeuge einen minimalen Java-Quelltext, der die Zeichenkette 'Hallo Welt' mit dem Graphics-Befehl drawString() in ein 500 x 500 Pixel großes Fenster schreibt."

Wir werden diesen Quelltext hier nicht besprechen. Probieren Sie ihn einfach mit BlueJ aus.

⇒ Klicken Sie auf den Übersetzen-Button von BlueJ. Die Anwendung müsste fehlerfrei übersetzt werden.
⇒ Klicken Sie dann mit der rechten Maustaste auf die Klasse Anwendung1 und wählen Sie den Befehl void main(String[] args).

Achtung: Nicht den Befehl new Anwendung1() anwählen, sondern den void main()-Befehl!

⇒ Es erscheint nun ein Dialogfenster; klicken Sie hier auf den OK-Button.

Dialogfenster zum Ausführen einer Anwendung

Es erscheint dann ein Fenster auf dem Bildschirm, das ungefähr 500 mal 500 Pixel groß ist. Mitten in diesem Fenster steht die Meldung "Hallo Welt":

Eine einfache Hallo-Welt-Anwendung

Damit haben Sie Ihre erste Java-Anwendung geschrieben. Bei den folgenden Übungen brauchen Sie sich nicht um das ganze Drumherum der Anwendungs-Quelltextes zu kümmern. Alle Veränderungen am Code, die Sie vornehmen, finden ausschließlich in der Methode paintComponent(...) der Anwendung statt:

   protected void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      g.drawString("Hallo Welt", 200, 200);
   }

Dieser Methode wird als Parameter ein Objekt der zentralen Klasse Graphics übergeben. Diese Klasse enthält die elementaren Zeichenbefehle wie drawString(...). In dieser Folge werden wir uns ausschließlich mit diesen Zeichenbefehlen befassen und dabei auch das Thema Schleifen vertiefen.

Übung 5.1-1

Die Zeichenkette "Hallo Welt" wird in dem Zeichenfenster an den Koordinaten (200,200) ausgegeben.

Experimentieren Sie mit den Koordinaten und lernen Sie so die Geometrie des Zeichenfensters kennen.

  • Lassen Sie die Zeichenkette "Links oben" möglichst nahe an der linken oberen Ecke erscheinen.
  • Lassen Sie gleichzeitig die Zeichenkette "Rechts unten" möglichst nahe an der rechten unteren Ecke erscheinen.
  • Probieren Sie anschließend weitere Positionen aus und beobachten Sie, wie sich die beiden Koordinaten auf die Lage der Zeichenkette auswirken.

Schritt 3 - einen Kreis zeichnen

Texte haben wir schon zur Genüge in den ersten vier Folgen ausgegeben, wir wollen uns in dieser Folge einmal auf die eigentlichen Zeichenbefehle der Klasse Graphics konzentieren. Der folgende Quelltext zeigt Ihnen, wie man drei farbige Kreise in dem Zeichenfenster positioniert.

protected void paintComponent(Graphics g)
{
   super.paintComponent(g);

   g.setColor(Color.RED);
   g.fillOval(30, 30, 80, 80);

   g.setColor(Color.BLUE);
   g.fillOval(170, 80, 120, 120);

   g.setColor(Color.GREEN);
   g.fillOval(340, 180, 60, 60);
}

Der erste Kreis wird in der Farbe Rot gezeichnet. Dazu wird der Graphics-Befehl setColor(Color.RED)) verwendet. Die Klasse Color stellt eine ganze Reihe von Farb-Konstanten zur Verfügung, u.a. RED, BLUE, GREEN, YELLOW, BLACK, WHITE und viele mehr.

Mit dem Befehl drawOval(...) wird ein Oval gezeichnet. Die beiden ersten Parameter geben die Koordinaten der Position des Ovals an, die beiden letzen Koordinaten legen die beiden Durchmesser des Ovals fest. Wenn beide Durchmesser den gleichen Wert haben wie in unserem Beispiel, werden Kreise gezeichnet.

Wir wollen die drei Kreise nun mit einem schwarzen Rand zeichnen. Am Beispiel des roten Kreises schauen wir uns einmal an, wie man einen farbigen Kreis mit einem schwarzen Rand zeichnet.

        g.setColor(Color.RED);
        g.fillOval(30, 30, 80, 80);
        g.setColor(Color.BLACK);
        g.drawOval(30, 30, 80, 80);   

Zunächst wird der rote Kreis mit fillOval() gezeichnet. Dann wird die Zeichenfarbe BLACK gewählt und ein schwarzer Kreis mit drawOval() gezeichnet. Die Methode drawOval() zeichnet nur den Umriss eines Kreises, während fillOval() die Fläche des Kreises zeichnet.

⇒ Ergänzen Sie den Quelltext so, dass auch die beiden anderen Kreise schwarze Ränder bekommen.

Ovale und Kreise

Ein normaler Mensch würde erwarten, dass man einen Kreis durch drei Parameter definieren kann: die Koordinaten des Mittelpunkts (x,y) sowie den Radius.

Java hat allerdings einen etwas anderen Weg gewählt, um Kreise und Ovale zu definieren. Schauen Sie sich dazu die folgende Abbildung an:

Die vier Parameter von drawOval()
Autor: Ulrich Helmich 2017, Lizenz: Public domain

Hier sehen wir ein Rechteck, das das Oval umgibt. Die beiden ersten Parameter der Methoden fillOval() und drawOval() bestimmen nun die x- und die y-Koordinate der linken oberen Ecke dieses umgebenden Rechtecks.

Die beiden letzten Parameter legen die Breite (width) und die Höhe (height) dieses Rechtecks fest.

Übung 5.1-2

In der Folge 4 haben Sie bereits for-Schleifen kennengelernt. Nutzen Sie dieses Wissen nun für eine grafische Anwendung.

Zeichnen Sie mithilfe einer for-Schleife 50 kleine rote Kreise nebeneinander in das Zeichenfenster. Verwenden Sie dazu die Methode fillOval(...).

Lösungen der Aufgaben und Übungen (Zugangsdaten erforderlich)

Schritt 4 - Farbige Objekte

Rechecke zeichnen

Die Klasse Graphics stellt zwei Befehle zum Zeichnen von Rechtecken zur Verfügung, nämlich drawRect(...) und fillRect(...). Die Parameter der Methoden sind die selben wie bei den beiden Oval-Methoden: Linke obere Ecke des Rechtecks, Breite und Höhe.

Mit

g.drawRect(10,10,300,200);

zeichnen wir also ein Rechteck links oben in das Zeichenfenster mit einer Breite von 300 Pixeln und einer Höhe von 200 Pixeln.

Farben

Wir wollen uns jetzt einmal näher mit den Farben beschäftigen. Die Klasse Color stellt bereits eine ganze Reihe von Farb-Konstanten zur Verfügung. Wir wollen jetzt aber eigene Farben erzeugen, die nicht durch diese Konstanten abgedeckt sind, beispielsweise zwanzig verschiedene Rot-Töne. Dazu müssen wir uns mit der Klasse Color näher vertraut machen.

Betrachten wir noch einmal diesen Befehl:

g.setColor(Color.RED);

Mit dieser Anweisung setzen wir die aktuelle Zeichenfarbe auf Rot. Auch mit dem folgenden Befehl können wir die Zeichenfarbe auf Rot setzen:

g.setColor(new Color(255,0,0));

Hier wird der Methode setColor() allerdings keine Farbkonstante mehr übergeben, sondern ein neu erzeugtes Objekt der Klasse Color.

Der hier eingesetzte Konstruktor der Klasse Color erwartet drei Parameter. Der erste Parameter (0..255) gibt den Rot-Anteil der zu erzeugenden Farbe an. Der zweite Parmeter legt den Grün-Anteil fest, und der dritte Parameter den Blau-Anteil.

Mit

g.setColor(new Color(0,255,0));

erzeugen wir ein reines Grün, und mit

g.setColor(new Color(0,0,255));

ein reines Blau. Ein reines Schwarz erhalten wir, wenn wir alle drei Parameter auf 0 setzen, und ein reines Weiß wird erzeugt, wenn alle Parameter den Wert 255 haben.

Übung 5.1-3

Verändern Sie die paintComponent(...)-Methode so, dass nur ein großer Kreis oder ein großes Rechteck dargestellt wird und experimentieren Sie dann mit dem Befehl

g.setColor(new Color(r,g,b));

herum, indem Sie für r, g und b verschiedene Werte zwischen 0 und 255 einsetzen.

Übung 5.1-4

Erzeugen Sie eine Zeichnung mit 20 nebeneinander liegenden Kreisen (oder Rechtecken).

Das erste Objekt (Kreis oder Rechteck ganz links) soll schwarz aussehen, der letzte Objekt (ganz rechts) rot (255,0,0). Die 18 dazwischen liegenden Objekte sollen Farbtöne haben, die einen zunehmenden Rot-Anteil besitzen, so wie auf der folgenden Abbildung zu sehen:

Lösungen der Aufgaben und Übungen (Zugangsdaten erforderlich)

Übung 5.1-5

Erzeugen Sie mithilfe von zwei geschachtelten for-Schleifen folgendes Muster:

Lösungen der Aufgaben und Übungen (Zugangsdaten erforderlich)

Schritt 5 - Die Klasse Circle

Zielsetzung:

Wir wollen eine eigene Klasse Circle erstellen, die Kreise zeichnet. Dabei wollen wir verschiedene Attribute definieren können: Position des Kreismittelpunkts (x,y), Radius des Kreises, Farbe der Kreisfläche, Farbe des Randes und Stärke des Randes in Pixeln.

Vorgehen:

Wir nutzen nur den Befehl g.fillOval(...). Zunächst wird ein Kreis in der Randfarbe gezeichnet, und anschließend zeichnen einen etwas kleineren Kreis mit der Flächenfarbe darüber. Wenn der Radius des Innenkreises nur 1 Pixel kleiner ist als der Radius des Außenkreises, erhalten wir einen Rand mit 1 Pixel Stärke.

Quelltext der ersten Version (ohne Rand)

import java.awt.*;

public class Circle
{
    private int xPos, yPos, radius;
    Color color;
    
    public Circle(int xPos, int yPos, int radius)
    {
       this.xPos = xPos;
       this.yPos = yPos;
       this.radius = radius;
    }
    
    public void setColor(Color color)
    {
       this.color = color;
    }
    
    public void paint(Graphics g)
    {
       g.setColor(color);
       g.fillOval(xPos-radius,yPos-radius,2*radius,2*radius);
    }
}

Damit diese Klasse auf die Graphics-Befehle zugreifen kann, muss die Bibliothek java.awt importiert werden.

Als Instanzvariable definieren wir xPos und yPos für den Kreismittelpunkt sowie radius für den Kreisradius. Die Farbe der Kreisfläche ist ein Objekt der Klasse Color. Die ersten drei Instanzvariablen werden - ohne Validierung - im Konstruktor initialisiert, die Instanzvariable color wird über eine eigene Setter-Methode festgelegt.

Man hätte den Konstruktor auch um einen vierten Parameter für die Farbe erweitern können, aber je mehr Parameter ein Konstruktor hat, desto unübersichtlicher wird das Ganze.

Bei der paint()-Methode müssen wir beachten, dass die Kreiskoordinaten in Java anders als in der Mathematik üblich definiert werden. Aus den Instanzvariablen xPos und radius wird die x-Koordinate der linken oberen Ecke des umgebenden Quadrats berechnet, und aus yPos und radius entsprechend die y-Koordinate.

Schauen wir uns nun eine Java-Anwendung an, die ein Objekt der Klasse Circle erzeugt und dann dessen paint()-Methode aufruft:

    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        g.drawLine(250,0,250,500);
        g.drawLine(0,250,500,250);
        
        Circle sonne = new Circle(250,250,100);
        sonne.setColor(Color.YELLOW);
        sonne.paint(g);
    }

Wir müssen nur die paintComponent(...)-Methode verändern, den Rest des Quelltextes können wir unverändert übernehmen.

Zunächst wird die paintComponent(...)-Methode der Oberklasse aufgerufen, dann wird ein blaues Koordinatenkreuz gezeichnet. Das machen wir, damit wir überprüfen können, ob der gelbe Kreis tatsächlich genau in der Mitte des Zeichenfensters erscheint.

Wir erzeugen dann ein Objekt der Klasse Circle, nennen es sonne und legen als Kreismittelpunkt den Wert (250,250) fest, also genau die Mitte der Zeichenfläche (500 x 500). Als Radius wählen wir 100 Pixel. Da es sich bei dem Kreis um eine Sonne handeln soll, setzen wir die Farbe auf Gelb, indem wir der Methode sonne.paint() die Konstante Color.YELLOW übergeben.

Die gelbe Sonne in der Mitte des Zeichenfensters
Autor: Ulrich Helmich 07/2026, Lizenz: Public Domain

Schritt 6 - Die nächsten Versionen

Die nächsten Versionen dieses Projekts erstellen Sie selbst in den folgenden Übungen. Wir gehen dabei ganz langsam und schrittweise vor, so dass Sie keine Probleme haben sollten, das Projekt zu vervollständigen.

Übung 5.1-6

  1. Damit wir die Position der zu erzeugenden Kreise besser kontrollieren können, ergänzen Sie das Koordinatenkreuz durch senkrechte und waagerechet blaue Linien im Abstand von 50 Pixeln. Verwenden Sie dazu nur eine while-Schleife!

  2. Das Koordinatenkreuz zeichnen Sie dann nicht mehr mit g.drawLine(...), sondern mit g.fillRect(...), damit die beiden Linien etwas kräftiger aussehen. Die Klasse Graphics verfügt leider über keine Möglichkeit, die Linienstärke zu definieren.

  3. Die Zeichenfläche ist nicht exakt 500 x 500 Pixel groß, sondern nur 500 x 470 Pixel, da offensichtlich die Menüleiste mit zur Zeichenfläche gerechnet wird. Um die Zeichenfläche wirklich auf 500 x 500 Pixel zu setzen, müssen wir die setSize()-Anweisung in der main()-Methode der Klasse Zeichenfenster etwas verändern: frame.setSize(500, 530);

Lösungen der Aufgaben und Übungen (Zugangsdaten erforderlich)

Übung 5.1-7

Erweitern Sie die Klasse Circle so, dass Kreise nicht nur ausgefüllt, sondern zusätzlich mit einem farbigen Rand in frei wählbarer Stärke gezeichnet werden können:

Hier wurde in der paintComponent(...)-Methode ein gelber Kreis (sonne) mit einem roten Rand der Stärke 5 sowie ein dunkelgelber kleiner Kreis (mond) mit einem blauen Rand der Stärke 1 erzeugt.

Für die Umsetzung gibt es mehrere Möglichkeiten. Beispielsweise können Sie

  • die Methode setColor(...) so erweitern, dass sie sowohl die Füllfarbe als auch die Randfarbe festlegt,
  • eine eigene Setter-Methode für die Randfarbe schreiben oder
  • eine gemeinsame Setter-Methode für Randfarbe und Randstärke implementieren.

Da Randfarbe und Randstärke nicht im Konstruktor von Circle festgelegt werden, sondern durch eigene Setter-Methoden, sollten Sie die beiden Instanzvariable auf jeden Fall im Konstruktor mit default-Werten initialisieren, beispielsweise Randfarbe = Schwarz und Randstärke = 1.

Lösungen der Aufgaben und Übungen (Zugangsdaten erforderlich)

Übung 5.1-8

Erstellen Sie nun eine Klasse Rectangle, mit der Rechtecke und Quadrate erzeugt werden können. Auch hier soll die Randfarbe und die Randstärke durch Setter-Methoden festgelegt werden.

Lösungen der Aufgaben und Übungen (Zugangsdaten erforderlich)