Programm weiter strukturieren

Zuerst lagern wir die Klasse Grafikobjekt in eine neue Datei aus.
Dann erzeugen wir in unserem Paket eine neue Klasse mit Namen StartFenster.java
und kopieren folgenden Quellcode hinein:

package miniMalen1;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JToolBar;
import javax.swing.SpinnerNumberModel;

public class StartFenster extends JFrame {

  public static void main(String[] s) {
    new StartFenster();
  }

  private ArrayList<Grafikobjekt> virtuellerBildschirm = new ArrayList<Grafikobjekt>();
  private JPanel panel;
  private int x = -10;
  private int y = -10;
  JSpinner linienstaerke;
  private JToolBar auswahl;

  public StartFenster() {
    initialisiereStartFenster();
  }

  private void initialisiereStartFenster() {
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setBounds(0, 0, 500, 500);
    this.setLocationRelativeTo(null);
    this.setAlwaysOnTop(true);
    this.setBackground(Color.white);
    this.setTitle("Tafel");
    this.setLayout(new BorderLayout());

    auswahl = new JToolBar();
    auswahl.setPreferredSize(new Dimension(300, 30)); // PreferredSize = bevorzugte Größe
    auswahl.setFloatable(true);
    this.add(auswahl, BorderLayout.PAGE_START);

    SpinnerNumberModel nummern = new SpinnerNumberModel(10, 1, 99, 1); // ( default, Minimum, Maximum, Schrittweite
                                      // )
    linienstaerke = new JSpinner(nummern);
    linienstaerke.setMinimumSize(new Dimension(50, 30)); // setzt die Mindestgröße ( Breite, Höhe )
    linienstaerke.setMaximumSize(new Dimension(50, 30)); // setzt die Maximalgröße

    auswahl.add(linienstaerke);
    
    Tafel tafel = new Tafel(this);
    this.add(tafel);

    sichtbar();
  }

  private void sichtbar() {
    this.setVisible(true);

  }
  
  public int getLinienstaerke() {
    int staerke = (int) this.linienstaerke.getValue();
    return staerke;
  }


}

Wie wir Zeile 23 entnehmen können darf der JSpinner nicht mehr privat sein, da wir ja von einer anderen Klasse aus darauf zugreifen müssen.

Es ist eine Methode getLinienstaerke hinzugekommen. In den Mauslistener MousePressed und MouseDragged müssen wir den Statuswert des Spinners auslesen. Da nun der Spinner in einem anderen Objekt liegt, würde die Zeile nochmals länger werden. Dadurch, das wir in der Methode getLinienstaerke bereits das Objekt das von getValue zurückgegeben wird, in ein int umwandeln, bleibt die aufrufende Zeile in den Mouselistener kürzer und damit übersichtlicher.

In Zeile 52 erstellen wir ein Objekt vom Typ Tafel. Damit die Tafel später auf die Variablen des StartFensters zugreifen kann, können wir die Referenz unseres StartFensters mit this übergeben, da wir uns ja in jenem befinden.

Kommen wir nun zur Datei Tafel.java:

package miniMalen1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JPanel;

public class Tafel extends JPanel implements MouseListener, MouseMotionListener {

  private ArrayList<Grafikobjekt> virtuellerBildschirm = new ArrayList<Grafikobjekt>();

  private int x = -10;
  private int y = -10;
  private StartFenster auswahl;

  public Tafel(StartFenster auswahl) {
    this.auswahl = auswahl;
    this.setBackground(Color.WHITE);
    this.addMouseListener(this);
    this.addMouseMotionListener(this);
  }

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

    {
      for (int z = 0; z < virtuellerBildschirm.size(); z++) {
        Grafikobjekt go = virtuellerBildschirm.get(z);
        g.fillOval(go.getKoordinaten().x, go.getKoordinaten().y, go.getStiftdicke(), go.getStiftdicke());
      }
    }

  }

  @Override
  public void mouseDragged(MouseEvent e) {
    System.out.println("Dragged");
    x = e.getX();
    y = e.getY();

    virtuellerBildschirm.add(new Grafikobjekt(new Point(x, y), auswahl.getLinienstaerke()));

    this.repaint();
  }

  @Override
  public void mouseMoved(MouseEvent e) {
    // TODO Automatisch generierter Methodenstub

  }

  @Override
  public void mouseClicked(MouseEvent e) {
    // TODO Automatisch generierter Methodenstub

  }

  @Override
  public void mouseEntered(MouseEvent e) {
    // TODO Automatisch generierter Methodenstub

  }

  @Override
  public void mouseExited(MouseEvent e) {
    // TODO Automatisch generierter Methodenstub

  }

  @Override
  public void mousePressed(MouseEvent e) {
    System.out.println("Pressed");
    x = e.getX();
    y = e.getY();

    virtuellerBildschirm.add(new Grafikobjekt(new Point(x, y), auswahl.getLinienstaerke()));

    this.repaint();
  }

  @Override
  public void mouseReleased(MouseEvent e) {
    // TODO Automatisch generierter Methodenstub

  }

}

Neu ist in Zeile 12, die beiden MouseListener die nun gleich in die Klasse implementiert wird.
Da wir die Klasse aufgrund der Trennung zum Startfenster nun gleich mit extends JPanel zu einem JPanel machen können, ist dies möglich und vereinfacht den Quelltext. Die Methoden für unsere Mauslistener können wir von Eclipse automatisch hinzufügen lassen, indem wir die Maus über den meist gelb oder rot unterstrichenen Klassennamen führen und dann das Angebot von Eclipse annehmen die benötigten Methoden einzufügen.

Weiter brauchen wir in Zeile 18 eine Variable StartFenster da wir im Konstruktor ja jenes StartFenster erwarten das wir in Zeile 52 von StartFenster.java übergeben haben.
Nachdem wir unsere Variable damit befüllt haben (Zeile 21) fügen wir dem JPanel noch die beiden MouseListener hinzu (implement allein reicht nicht, man muss explizit angeben welche Objekte welchen Mouselistener erhalten sollen).

Auch die bisherige initialisiere.. Methode fällt weg, da wir Buttons und Spinner ja ausgelagert haben.

Schließlich finden wir in Zeile 45 und 80 die Zeile in der wir unserem virtuellem Bildschirm ein Grafikobjekt hinzufügen. Hier müssten wir, falls wir im StartFenster keine Methode getLinienstaerke definiert hätten
(int) auswahl.linienstaerke.getValue() statt auswahl.getLinienstaerke()
schreiben, was den Quellcode wesentlich unübersichtlicher machen würde.

Zuallerletzt fallen noch einige Importe weg, die überflüssig geworden sind, da sie bereits im StartFenster importiert wurden.

Im nächsten Kapitel wollen wir folgende Funktion implementieren:
Zwei verschiedene Werkzeugspitzen, Kreis und Quadrat.