1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet

Die Koordinate x wird auf jeden Fall gesetzt werden, wenn der Listener für eine Komponenten registriert ist und die rechte Pfeiltaste gedrückt wurde. Aber selbst dann wird es vermutlich nicht das Verhalten mit sich bringen, welches du erwartest.

Du würdest zum einen mit jedem Druck auf die rechte Pfeiltaste ein neues Rect-Objekt anlegen und für dieses den x-Wert setzen. Gezeichnet würde es auch nie werden, denn du hängst es ja nie irgendwo an eine entscheidende Komponente (Frame oder Panel).

Neben den vielen unnötigen Leerzeilen kann so einiges anderes raus.

1) Die komplette Klasse Rect ist an sich überflüssig. Stattdessen gibt es die Rectangle-Klasse aus AWT. Wenn du von einer JLabel-Komponente bspw. getBounds aufrufst, bekommst du eine Instanz von Rectangle zurück.

2) Nach Konvention beginnen eigentlich alle Variablen (Ausnahme: Sichtbare, konstante Felder) mit einem Kleinbuchstaben. Da wären also Width und Height ebenfalls mit eingeschlossen. Seien sie Felder oder Parameter.

3) In paintComponent erzeugst du ebenfalls nochmal ein Rect-Objekt, gebrauchst es aber nie. Genauso wie diese Zeile, ist auch der Aufruf von repaint ohne Sinn. Hinsichtlich Punkt 1 würde ich nun nur vermuten, dass du eigentlich das Rechteck zeichnen und Schritt für Schritt bewegen wolltest?

4) Wo die create-Methode verwendet wird, ist nicht ersichtlich. Wäre es nicht generell sinnvoller, stattdessen einen passenden Konstruktor zu definieren?

Der setVisible-Aufruf ist jedenfalls auch hier unnötig.

5) Genauso, wie nicht klar ist, ob du eine Instanz deines Listeners überhaupt erstellst und an ein Frame o.ä. hängst, lässt sich nicht ausmachen, ob du eine Draw-Instanz überhaupt einmal erzeugst und an deine Oberfläche bindest.

Ein kleines Beispiel von einem Rechteck, welches seine Position ändert, könnte so aussehen:

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

public class Main {
  public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
      Board board = new Board();

      JFrame frame = new JFrame("Move something");
      frame.addKeyListener(new KeyHandler(board));
      frame.add(board);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
    });
  }
}

class Board extends JLabel {
  private Rectangle block;

  public Board() {
    this.block = new Rectangle(50, 50, 50, 50);
  }

  public Rectangle getBlock() {
    return block;
  }

  @Override
  public Dimension getPreferredSize() {
    return new Dimension(300, 300);
  }

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

    graphics.setColor(Color.orange);
    graphics.drawRect(block.x, block.y, block.width, block.height);
  }
}

class KeyHandler implements KeyListener {
  private Board board;

  public KeyHandler(Board board) {
    this.board = board;
  }

  @Override
  public void keyTyped(KeyEvent e) {
  }

  @Override
  public void keyPressed(KeyEvent e) {
    switch (e.getKeyCode()) {
      case KeyEvent.VK_RIGHT:
        board.getBlock().x = 150;
        board.repaint();
        break;
    }
  }

  @Override
  public void keyReleased(KeyEvent e) {
  }
}

Natürlich sollte jede Klasse ihre eigene Datei bekommen.

Das ich direkt auf die Felder der Rectangle-Klasse zugreife, ist der Einfachheit halber geschuldet. Es gibt auch Getter (bei denen dann ein Typecast von double zu int nötig wäre) und das Setzen/Ändern von Position und Breite geschieht üblicherweise paarweise.

Wenn dein Versuch nun der erste Ansatz für ein Spiel werden sollte, eine Warnung vorweg: Swing wurde nicht für die Entwicklung von Spielen konzipiert. Stattdessen solltest du auf andere Tools zurückgreifen. Sei es Slick2D, libGDX, Processing (Core-Lib), FXGL oder LWJGL. Es gibt viele zielgerichtete Optionen, die zudem einfacher handhabbar sind, als der Zeichenprozess in Swing.


Antoz2001 
Fragesteller
 22.04.2020, 12:31

Ok, vielen dank, dann werde ich es sofort ausprobieren.

0