Java: In einem Fenster Zeichnen?

2 Antworten

Hier ein einfaches Beispiel:

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

public class GUI extends JFrame {
    public GUI(String t) {
        super(t);

        setSize(new Dimension(500, 500));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setContentPane(new Canvas());
    }

    public static void main(String[] args) {
        var gui = new GUI("Fenstertitel");
        gui.setVisible(true);
    }
}

Canvas ist die Klasse, in der das Zeichnen implementiert wird:

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

public class Canvas extends JPanel {
    private Rect rect1 = new Rect(20, 20, 300, 200);
    private Rect rect2 = new Rect(200, 200, 300, 100);

    public Canvas() {
        var timer = new Timer(20, e -> {
            rect2.getRectangle().grow(-1, 2);
            repaint();
        });
        timer.start();
    }

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

        rect1.fill(g);
        rect1.draw(g);

        rect2.fill(g);
        rect2.draw(g);
    }
}

Die Funktion, die an Timer() übergeben wird, wird einmal alle 20 Millisekunden aufgerufen. Mit repaint() wird der Canvas aktualisiert. Dabei wird paintComponent() aufgerufen.

In paintComponent() werden zwei Rechtecke gezeichnet. Ich habe dafür diese Hilfsklasse erstellt, die die Koordinaten und zwei Farben enthält:

import java.awt.*;

/**
 * A rectangle to draw on the canvas
 */
public class Rect {
    /**
     * Coordinates of the rectangle
     */
    private Rectangle rectangle;
    /**
     * Line color
     */
    private Color draw;
    /**
     * Fill color
     */
    private Color fill;

    public Rect(Rectangle r, Color draw, Color fill) {
        this.rectangle = r;
        this.draw = draw;
        this.fill = fill;
    }

    public Rect(int x, int y, int width, int height) {
        this(new Rectangle(x, y, width, height), Color.BLACK, Color.GRAY);
    }

    public void draw(Graphics g) {
        g.setColor(draw);
        g.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
    }

    public void fill(Graphics g) {
        g.setColor(fill);
        g.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    public Color getDrawColor() {
        return draw;
    }

    public Color getFillColor() {
        return fill;
    }

    public void setRectangle(Rectangle r) {
        this.rectangle = r;
    }

    public void setDrawColor(Color draw) {
        this.draw = draw;
    }

    public void setFillColor(Color fill) {
        this.fill = fill;
    }
}
Woher ich das weiß:Studium / Ausbildung – Informatikstudium
(...) falls andere Varianten besser sind könnt ihr mir das sagen (...)

Statt mit Swing zu zeichnen, würde ich dir empfehlen, die Kernbibliothek von Processing einzubinden (lies hier). Diese ist besser für das Zeichnen von Animationen ausgelegt und auch einfacher in der Handhabung.

(...) bei Recherche bin ich auch auf Vector gestoßen, (...)

Diese Klasse dient als Datenspeicher, so wie Arrays oder Listen. Es ist nicht die mathematische Klasse, die du vermutlich erwartest.

Ich würde gerne mit mehreren Klassen es übersichtlicher gestalten, also eine Main, GUI, Variablen, Movement, etc.

Orientiere dich an dem MVC Pattern.

Und danach wird mit einer paint Methode gezeichnet (...)

Wenn du mit Swing zeichnest, solltest du nicht die paint-Methode zum Zeichnen verwenden. Sie ruft implizit drei andere Methoden auf: paintComponent, paintBorder und paintChildren. Es besteht aber überhaupt kein Grund, diese anzufassen.

Erstelle dir stattdessen eine Klasse, die von JPanel erbt und hänge eine Instanz derer an den Frame:

class DrawBoard extends JPanel {
  // ...
}

// main or where ever you create your frame:
JFrame frame = new JFrame("My rectangles");
// ...
frame.add(new DrawBoard());
frame.setSize(400, 400);
frame.setVisible(true);

Innerhalb der neuen Klasse kannst du paintComponent überschreiben.

@Override
protected void paintComponent(Graphics graphics) {
  // draw here ...
}

Auf die Attribute deiner Rechtecke kannst du durchaus Zugriff ausüben. Die Liste mit Rechtecken sollte als Attribut in der Klasse zur Verfügung stehen. Wenn du die Attribute der Rechtecke wiederum änderst, wirkt sich das auf den nächsten Zeichenvorgang von Swing aus.

Beispiel:

// inside paintComponent:
super.paint(graphics);

for (Rectangle rectangle : this.rectangles) {
  graphics.drawRect(rectangle.getX(), rectangle.getY(), rectangle.getWidth(), rectangle.getHeight());
  rectangle.incrementX();
}

Bei jedem Zeichenvorgang könnte nach dem Zeichnen die Position von x um eins erhöht werden. So eine Veränderung kannst du natürlich auch außerhalb der Methode triggern.

Bezüglich des Zeichnens in Swing solltest du hier weiterlesen:

Fafnira100 
Fragesteller
 05.02.2020, 10:16

Danke auf jeden Fall ^^ Du und der andere Antworter haben mir sehr geholfen ^^ Ich habe es auch ausprobiert nur bei deinen Code habe ich immer Fehlermeldungen bekommen beim ausführen. Das lag glaube ich in deiner paintcomponent Methode.

ich habe danach das „super.paint(g)“ durch ,,super.paintComponent(g) ersetzt und das hat dann geklappt

0
regex9  05.02.2020, 12:54
@Fafnira100

Ja, mit super.paint habe ich mich oben verschrieben.

0