Home > Informatik > Einführung in die OOP > 3. Schleifen > 3.4 For-Schleifen mit Graphiken

3.4 Schleifen mit Graphiken

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. Der Quelltext ist ausführlich kommentiert und muss daher hier nicht weiter erläutert werden.

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);
        
        // Beispiel-Graphiken
        
        // 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:

  1. drawLine(xStart,yStart,xEnde,yEnde);
  2. drawRect(xLinksoben, yLinksoben, breite, hoehe);
  3. fillRect(xLinksoben, yLinksoben, breite, hoehe);
  4. drawOval(xLinksoben, yLinksoben, breite, hoehe);
  5. 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 müssen Sie dann 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ß.

Nun zu den Aufgaben

Die ganze Geschichte mit der Graphik-Anwendung hat eigentlich nur die Aufgabe, Ihnen die nächsten Aufgaben mit for-Schleifen etwas "schmackhafter" zu machen. Wir fangen aber ganz leicht an.

Die Aufgaben stehen übrigens auch als Arbeitsblatt zur Verfügung, das Sie sich hier herunter laden können.

Ü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!

Ein kleiner Funktionsplotter

Wir nehmen uns nun ein größeres Graphik-Projekt vor. Ich habe ChatGPT veranlasst, eine möglichst einfache Java-Anwendung mit einer Zeichenfläche, einer Editbox und einem OK-Button zu erstellen.

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 und von mir 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("Minimal-App mit Textfeld, Button und Zeichenfläche");
        dieApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        dieApp.setSize(800, 630);

        // Haupt-Panel nimmt den gesamten Bereich der App ein
        hauptPanel = new JPanel(null);
        hauptPanel.setBackground(new Color(220, 220, 220)); // grauer Hintergrund
        dieApp.setContentPane(hauptPanel);

        // 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);
        hauptPanel.add(zeichenPanel);

        // Textfeld 160 x 40, erscheint im Haupt-Panel
        tf = new JTextField();
        tf.setBounds(20, 20, 160, 40);
        hauptPanel.add(tf);

        // OK-Button 160 x 40, auch im Haupt-Panel
        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)
       {
           // Achtung: Hier findet keine Überprüfung des Textes statt,
           // ob es sich dabei wirklich um eine Zahl handelt.
           // Falscheingaben führen zu einem Laufzeitfehler.
           wert = Double.parseDouble(tf.getText());
           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 vom Typ 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.

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 Werte 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.

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. Die Pfeile an den Enden sind nicht unbedingt notwendig.

Ausbau-Aufgaben

Von dieser Stelle an sind Sie auf sich selbst gestellt. Sie können die Funktionsplotter-App nach Belieben erweitern, zum Beispiel

  • Darstellung von Funktionen 3. und 4. Grades
  • Der Benutzer kann den Definitionsbereich eingeben, zum Beispiel -5 bis +15
  • Der Benutzer kann den Wertebereich festlegen und damit die Skalierung der y-Achse.
  • Zusätzliche Darstellung der 1. Ableitung der Funktion
  • Abfangen von Fehlern bei der Eingabe der Koeffizienten
  • und und und

Seitenanfang
Weiter geht's noch nicht ...