Ein paar schöne Graphiken
Wir wollen unsere Fertigkeiten im Umgang mit Schleifen nun in einer graphischen Umgebung vertiefen. Betrachten wir eine sehr einfache Java-Anwendung, die Linien, Rechtecke und Kreise darstellt. Hier der Quelltext, den Sie sich bitte in ein neues Java-Projekt hineinkopieren und ausprobieren.
import java.awt.*;
import javax.swing.*;
public class Anwendung extends JPanel
{
public static void main(String[] args)
{
JFrame f = new JFrame("Einfachste Java-Anwendung");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
f.add(new Anwendung());
f.setVisible(true);
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// Horizontale Linie
g.drawLine( 50, 50,700, 50);
// Senkrechte Linie
g.drawLine(250,50,250,500);
// roter Rahmen mit 10 Pixel Abstand zum Rand
// Fenstergröße wird als konstant angesehen 800 x 600 Pixel
g.setColor(Color.RED);
g.drawRect(10,10,780,550);
// hellgelbes Quadrat mit schwarzem Rand
g.setColor(new Color(230,230,191));
g.fillRect(300,300,200,200);
g.setColor(Color.BLACK);
g.drawRect(300,300,200,200);
// roter Kreis mit dickem blauen Rand
g.setColor(Color.BLUE);
g.fillOval(300,100,50,50);
g.setColor(new Color(255,0,0));
g.fillOval(305,105,40,40);
}
}
Sie werden sicherlich sehr schnell herausbekommen, wie man den Titel des Fensters und seine Breite und Höhe ändern kann. Für Sie wichtig sind die Beispiel-Graphiken in der Methode paintComponent(). Machen Sie sich die fünf elementaren Graphik-Befehle der Klasse Graphics klar:
- drawLine(xStart,yStart,xEnde,yEnde);
- drawRect(xLinksoben, yLinksoben, breite, hoehe);
- fillRect(xLinksoben, yLinksoben, breite, hoehe);
- drawOval(xLinksoben, yLinksoben, breite, hoehe);
- fillOval((xLinksoben, yLinksoben, breite, hoehe);
Dabei zeichnen drawRect() und drawOval() leere Rechtecke und Ovale mit einem 1 Pixel breiten Rand in der aktuellen Farbe. Die Methoden fillRect() und fillOval() dagegen zeichnen Rechtecke und Ovale, die mit der aktuellen Farbe ausgefüllt sind.
Für das Ändern der Farbe gibt es den Befehl setColor(), der als Parameter entweder eine Farb-Konstante wie Color.RED oder Color.BLACK annimmt, oder ein "frisch" erzeugtes Objekt der Klasse Color. Bei der Erzeugung eines Color-Objektes müssen Sie die drei Farbwerte für Rot, Grün und Blau als Zahlen zwischen 0 und 255 übergeben. Beispielweise erzeugen Sie mit new Color(255,255,0) die Farbe Gelb und mit new Color(255,255,191) ein sehr helles Gelb. Mit (0,0,0) haben wir die Farbe Schwarz, und mit (255,255,255) die Farbe Weiß.
Aufgaben
Diese Aufgaben stehen übrigens auch als Arbeitsblatt zur Verfügung, das Sie sich hier herunter laden können.
Bei den nächsten Aufgaben müssen Sie nur die Methode paintComponent()bearbeiten. Sie können zunächst alle Befehle in der kopierten Vorlage löschen und durch eigene ersetzen. Allerdings muss der Aufruf super.paintComponent() weiterhin der erste Befehl in der Methode bleiben, da hier die entsprechende Methode der übergeordneten Klasse aufgerufen wird.
Übung 3.4 #1
Füllen Sie das Graphik-Fenster mit 100 senkrechten Linien mit gleichem Abstand. Die Linien sollen das Fenster gleichmäßig ausfüllen:

Diese Graphik wurde mit einer for-Schleife erzeugt. Für die nächste Aufgabe eignet sich vielleicht eine while-Schleife besser.
Übung 3.4 #2
Wie Aufgabe 1, nur soll der Abstand zwischen den Linien kontinuierlich zunehmen, erst 2 Pixel, dann 3 Pixel, dann 4 Pixel und so weiter. Der rechte Rand des Fensters soll aber nicht ganz erreicht werden.

Diese Graphik wurde mit einer while-Schleife erstellt. Auch der Fenster-Titel wurde angepasst.
Übung 3.4 #3
Erstellen Sie mit Hilfe von zwei geschachtelten for-Schleifen folgende Abbildung:

Jetzt spielen wir zusätzlich mal mit den Farben herum.
Übung 3.4 #4
Erzeugen Sie folgende Graphik:

Hier wurden die Farben mit dem Color(r,g,b)-Befehl erzeugt, wobei die Werte von r und g von den Laufvariablen der beiden for-Schleifen bestimmt werden.
Nach diesen noch recht einfachen Übungen wird es jetzt etwas schwerer.
Übung 3.4 #5
Zeichnen Sie ein Schachbrett:

Bei dieser Zeichnung wurde die Zeichenfläche auf 800 x 800 Pixel vergrößert.
Die verwendeten Farben sind:
Color hell = new Color(240, 217, 181);
Color mittel = new Color(181, 136, 99);
Color dunkel = mittel.darker();
Interessant ist hier die Verwendung der Methode darker() der Klasse Color, um eine dunklere Variante einer Farbe zu erzeugen.
Und noch eine kleine Randbedingung: Der Quelltext sollte möglichst kompakt sein!
Für Fortgeschrittene, nicht klausurrelevant!
Projekt Funktionsplotter
Dieser Teil der Folge 3.3 ist für Fortgeschrittene gedacht, die bereits recht große Java-Kenntnisse haben.
Wir sehen hier eine einfache Java-Anwendung mit einem Textfeld, einem Button und einem Zeichen-Panel:
Die graphische Benutzeroberfläche der Java-Anwendung (GUI)
In die Editbox gibt man einen String ein, und wenn man auf den OK-Button klickt, dann wird dieser String in der Zeichenfläche oben links in großer Schrift angezeigt.
Hier der von ChatGPT erzeugte und von mir dann etwas überarbeitete und kommentierte Quelltext der gesamten Anwendung:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Anwendung implements ActionListener
{
private double wert = 0.0; // Default-Wert
private JTextField tf;
private JButton ok;
private JPanel hauptPanel, zeichenPanel;
private JFrame dieApp;
public Anwendung()
{
// Fenster der App definieren
dieApp = new JFrame("App mit Textfeld, Button und Zeichenfläche");
dieApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dieApp.setSize(800, 630);
// Ein Panel ist eine Fäche innerhalb eines Fensters, auf der man
// Inhalte anzeigen oder anordnen kann.
// Alle Panel-Objekte sind Objekte der Klasse JPanel.
// 1. Haupt-Panel
hauptPanel = new JPanel(null);
hauptPanel.setBackground(new Color(220, 220, 220)); // grauer Hintergrund
dieApp.setContentPane(hauptPanel);
// 2. Zeichen-Panel 560 x 560, weiß. Hier kann gezeichnet werden.
zeichenPanel = new JPanel()
{
@Override
protected void paintComponent(Graphics g)
// Dies ist die wichtigste Methode der ganzen App!
// Hier bauen Sie die Lösungen der folgenden Aufgaben ein.
{
super.paintComponent(g);
g.setFont(new Font("SansSerif", Font.BOLD, 24));
g.setColor(Color.BLACK);
g.drawString(String.valueOf(wert), 30, 50);
}
};
zeichenPanel.setBackground(Color.WHITE);
zeichenPanel.setBounds(220, 20, 560, 560);
// Jetzt wird das Zeichen-Panel dem Haupt-Panel hinzugefügt
hauptPanel.add(zeichenPanel);
// Hier werden dem Haupt-Panel ein Textfeld und ein Button
// hinzugefügt.
// 1. Textfeld 160 x 40
tf = new JTextField();
tf.setBounds(20, 20, 160, 40);
hauptPanel.add(tf);
// 2. OK-Button 160 x 40
ok = new JButton("OK");
ok.setBounds(20, 70, 160, 40);
ok.addActionListener(this);
hauptPanel.add(ok);
dieApp.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent event)
// Diese Methode dient zum Abfangen von Ereignissen
// In dieser App ist eigentlich nur das Anklicken des OK-Buttons
// das entscheidende Ereignis
{
if (event.getSource() == ok) // wurde der OK-Button geklickt?
{
// Achtung: Hier findet keine Überprüfung des Textes statt,
// ob es sich dabei wirklich um eine Zahl handelt.
// Falscheingaben führen zu einem Laufzeitfehler.
// Die Instanzvariable wert wird in eine double-Zahl umgewandelt
// Dazu wird die Methode getText() der Klasse JTextField aufgerufen
// Das Umwandeln macht die Methode parseDouble() der Klasse Double.
wert = Double.parseDouble(tf.getText());
// Neuzeichnen des Zeichen-Panels
zeichenPanel.repaint();
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> new Anwendung());
}
}
Dank der vielen Kommentare, die ich eingefügt habe, muss dieser Quelltext eigentlich nicht mehr beschrieben werden. Wie bereits in den Kommentaren gesagt, ist die folgende paintComponent()-Methode für Sie die wichtigste:
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setFont(new Font("SansSerif", Font.BOLD, 24));
g.setColor(Color.BLACK);
g.drawString(String.valueOf(wert), 30, 50);
}
Wenn Sie den angezeigten Text durch ein rotes Quadrat ersetzen wollen, ändern Sie die paintComponent()-Methode folgendermaßen:
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(50,50,100,100);
}
Machen Sie sich mit der Anwendung vertraut und bauen Sie noch ein paar andere Graphiken in das Zeichen-Panel ein. Danach können Sie sich dem nun folgenden Projekt zuwenden.
Projekt-Aufgabe 1
Wir wollen einen kleinen Funktionsplotter bauen, der den Verlauf einer quadratischen Funktion anzeigt. Eine quadratische Funktion besitzt drei Koeffizienten, die meistens als a, b und c bezeichnet werden:
f(x) = a*x2 + b*x + c
Ihre erste Aufgabe wäre es also, die Java-Anwendung um zwei weitere Textfelder der Klasse JTextField zu ergänzen. Die drei Textfelder sollten dann gleich groß sein und untereinander angeordnet sein. Unter den drei Textfeldern sollte sich dann der OK-Button befinden.
In dem Zeichen-Panel lassen Sie dann die drei eingelesenen Zahlen untereinander anzeigen. Es findet noch keine Fehlerüberprüfung statt, Fehleingaben führen zu einem Laufzeitfehler. Also geben Sie bitte nur Zahlen in die drei Textfelder ein.

Projekt-Aufgabe 2
Die Funktion f(x) soll im Bereich von -10 bis +10 in der Zeichenfläche angezeigt werden. Lassen Sie dazu in einer for- oder while-Schleife den Wert von x anwachsen und berechnen Sie den jeweiligen y-Wert, also
y = a*x*x + b*x + c;
An der jeweiligen Position (x,y) zeichnen Sie einen kleinen Kreis oder ein kleines Quadrat (Durchmesser nur 3 oder 4 Pixel).
Denken Sie daran, dass die y-Werte in dem Zeichen-Panel nach unten hin zunehmen, der obere Rand des Panels hat den y-Wert 0, der untere Rand aber den y-Wert 560. Bei einem Funktionsgraphen dagegen befinden sich die positiven y-Werte oben, die negativen unten. Hier müssen Sie jetzt gut nachdenken, damit die Kreise auch an der richtigen Position gezeichnet werden.
Testen Sie Ihre App nun, in dem Sie in die drei Text-Felder unterschiedliche Zahlenwerte eingeben und dann den OK-Button klicken. Es sollte immer eine Parabel in der Zeichenfläche erscheinen.
Vergessen Sie nicht das Koordinatenkreuz. Die x-Achse sollte ungefähr mittig durch das Panel verlaufen, die y-Achse ebenso.
Eine erste Version des Funktionsplotters
Hier sehen wir schon eine erste Version des Funktionsplotters.
Zwischenaufgabe
Bevor wir mit dem Projekt weitermachen, wollen wir ein kleines Refactoring durchführen.
Lagern Sie die Befehle zum Zeichnen der Koordinatenachsen in eine eigene Methode
public void zeichneAchsen(Graphics g)
aus und die Befehle zum Zeichnen des Funktionsgraphen in eine eigene Methode
public void zeichneFunktion(Graphics g)
aus. Diese beiden Methoden können Sie dann innerhalb von paintComponent() aufrufen:
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
zeichneAchsen(g);
zeichneFunktion(g);
}
Dadurch soll die Methode paintComponent() entlastet werden, so dass Sie sich besser auf das Zeichnen der Achsen und des Funktionsgraphen konzentieren können.
Nun können wir uns ganz auf das Zeichnen der Koordinatenachsen konzentrieren. Also auf zur nächsten "richtigen" Aufgabe.
Projekt-Aufgabe 3
Ergänzen Sie das Koordinatenkreuz um sinnvolle Einteilungen und Beschriftungen. Es reicht, wenn Sie die Positionen -10, -5, 5 und 10 auf den beiden Achsen beschriften.

So könnten die Achsen beispielsweise aussehen.
Für die kleinen Striche auf den beiden Achsen verwenden Sie wieder je eine for- oder while-Schleife, und die Beschriftung erzeugen Sie mit dem drawString()-Befehl der Klasse Graphics.
Eventuell müssen Sie durch Ausprobieren herausfinden, welche Koordinaten Sie für die Ziffern wählen müssen. Je nach gewähltem Zeichensatz können die Ziffern leicht nach links, rechts, oben oder unten verschoben sein, dann müssen Sie manuell nachhelfen.
// Beschriftung der x-Achse
g.setFont(new Font("SansSerif", Font.PLAIN, 12));
g.drawString("-10", yAchseX - skalierung*10-10, xAchseY + 30);
g.drawString("-5", yAchseX - skalierung* 5-7, xAchseY + 30);
g.drawString("5", yAchseX + skalierung* 5-3, xAchseY + 30);
g.drawString("10", yAchseX + skalierung*10-7, xAchseY + 30);
Hie sehen Sie einen Ausschnitt aus der Methode zeichneAchsen(). Bei dem gewählten Font "SansSerif" der Größe 12 musste die Position der Ziffern leicht korrigiert werden. Die Instanzvariable skalierung hat hier den Wert 20. Durch diese Instanzvariable wird sichergestellt, dass die Achsen in dem gleichen Maßstab gezeichnet werden wie der Funktionsgraph. Eine Einheit auf der X- bzw. Y-Achse entspricht 20 Pixeln.
Ändert man den Wert dieser Instanzvariable beispielsweise auf 10, dann erhält man folgendes Bild:

Falls Sie bereits über fortgeschrittene Java-Kenntnisse verfügen, können Sie ja mal versuchen, den Funktionsplotter in verschiedener Hinsicht zu erweitern. Beispielsweise könnte man den Definitionsbereich der Funktion über zwei Textfelder einlesen und dann den Skalierungsfaktor entsprechend berechnen lassen. Oder Sie zeichnen nicht nur die Funktion, sondern in einer anderen Farbe auch deren 1. Ableitung ein. Vielleicht haben Sie selbst ja auch noch interessante Ideen, die Sie dann bei der nächsten Sitzung einmal vorführen.
Zur Klausur
Das Funktionsplotter-Projekt geht weit über die Anforderungen hinaus, die in der Klausur gestellt werden, es ist eigentlich für Leute gedacht, die sich in der Vorlesung langweilen, weil sie schon alles mal gehört haben. Also geraten Sie nicht in Panik, wenn Sie Probleme mit diesem Projekt haben. In der Klausur werden nur Aufgaben mit Konsolen-Ausgabe behandelt.
Seitenanfang
Weiter mit Folge 4: Arrays