actionperformed wird nicht aufgerufen/ repaint()

Jackcarver12

Mitglied
Hallo Leute,
ich hätte mal eine Frage zu meinem Code:

Sollte in Richtung Snake gehen und sehr simpel ausfallen:

[CODE lang="java" title="MeinPanel"]package nh;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JPanel;



public class Panel extends JPanel implements ActionListener {



static final int screenWidth = 600;
static final int screenHeight = 600;
static final int snakesize = 25;
static final int gameUnits = (screenWidth * screenHeight) / snakesize;
static final int delay = 55;


public boolean running = false;

protected Snake snake;
//protected Apple apple;
protected Random random;

public Panel()
{
random = new Random();
snake = new Snake();
this.setPreferredSize(new Dimension(screenWidth, screenHeight));
this.setBackground(Color.BLACK);
this.setFocusable(true);
this.addKeyListener(new Adapter(snake));

}

public void actionPerformed(ActionEvent e) {
System.out.println("Test");

if (running) {
// move();
//checkCollisions();
}
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}

public void draw(Graphics g) {
// drawGrid(g);
drawSnake(g);
// drawApple(g);
}
private void drawSnake(Graphics g) {
g.setColor(Color.GREEN);
//set Color for Head
g.fillRect(snake.getHead().getPosX(), snake.getHead().getPosY(), snakesize, snakesize);
//wenn die schlange Komponenten hat
if(snake.getTail().size()>0)
for(int i=0; i<snake.getTail().size();i++)
{
Component c = (Component) snake.getTail().get(i);
g.fillRect(c.posX, c.posY, snakesize, snakesize);
}
}

/*
private void drawSnake(Graphics g) {
g.setColor(Color.GREEN);
for (int i = 0; i < snake.length; i++) {
g.fillRect(snake.XPositions, snake.YPositions, unitSize, unitSize);
}
}

*/

}
[/CODE]

[CODE lang="java" title="AdapterCode"]package nh;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;


public class Adapter extends KeyAdapter {

static final int screenWidth = 600;
static final int screenHeight = 600;
static final int snakesize = 25;
static final int rasterfeld = (screenWidth * screenHeight) / snakesize;
static final int delay = 75;
private final int startXPosition = (int) (rasterfeld / 2);
private final int startYPosition = (int) (rasterfeld / 2);

private Snake snake;
private Direction dir;

public Adapter(Snake snake)
{
this.snake=snake;




}

public void keyPressed(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_RIGHT:
System.out.println("nachRechts");
snake.dir = dir.Right;
snake.getHead().setPosX(snake.getHead().getPosX()+snakesize);
break;
case KeyEvent.VK_LEFT:
System.out.println("nachLinks");
snake.dir= dir.Left;
snake.getHead().setPosY(snake.getHead().getPosX()-snakesize);
break;
case KeyEvent.VK_UP:
System.out.println("nachOben");
snake.dir = dir.Up;
snake.getHead().setPosX(snake.getHead().getPosY()+snakesize);
break;
case KeyEvent.VK_DOWN:
System.out.println("nachUnten");
snake.dir = dir.Down;
snake.getHead().setPosX(snake.getHead().getPosY()-snakesize);

break;

}

}

}
/*

case KeyEvent.VK_RIGHT:
if (snake.direction != Panel.Direction.Left) {
snake.direction = Panel.Direction.Right;
}
break;

case KeyEvent.VK_LEFT:
if (snake.direction != GamePanel.Direction.Right) {
snake.direction = GamePanel.Direction.Left;
}
break;

case KeyEvent.VK_UP:
if (snake.direction != GamePanel.Direction.Down) {
snake.direction = GamePanel.Direction.Up;
}
break;

case KeyEvent.VK_DOWN:
if (snake.direction != GamePanel.Direction.Up) {
snake.direction = GamePanel.Direction.Down;
}
break;
*/[/CODE]

er geht in die ActionPerformed nicht rein....
und somit kann ich leider auch den Schlangekopf nicht bewegen!
Die Key-Eingaben bekomme ich.

Was mache ich falsch?
Kann mir jemand vielleicht einen Tipp geben?
LG J
 

Anhänge

  • Ausgabe.PNG
    Ausgabe.PNG
    2 KB · Aufrufe: 2
  • snake.PNG
    snake.PNG
    2 KB · Aufrufe: 2
Dein Panel implementiert zwar das Interface ActionListener, aber die Instanz wird ja nirgends als ActionListener eingetragen. Daher wird das auch nie aufgerufen.
 
Vielen Dank,
aber wenn man diesen Teil meines Codes betrachtet:
[CODE lang="java" title="Panel Konstruktor" highlight="8"] public Panel()
{
random = new Random();
snake = new Snake();
this.setPreferredSize(new Dimension(screenWidth, screenHeight));
this.setBackground(Color.BLACK);
this.setFocusable(true);
this.addKeyListener(new Adapter(snake,this));
startGame();

}[/CODE]

dann füge ich doch den Adapter hinzu...
und in diesem Adapter sind sämtliche Listener implementiert.
Im Adapter geht er in die Methoden die ich benötige
Aber die ActionPerformed wird nie aufgerufen, was ich meinen fehlenden Sysouts entnehmen kann.


snake2.PNG
der auskommentierte Teil, stellt meinen Versuch dar, das Ganze über einen "inner ActionListener" umzusetzen. Kommentiere ich das Ganze ein, so meckert er und sagt, dass er seine ActionPerformedMethode nicht findet. So gesehen hätte ich ja dann 2 Action Performed Methoden.
Dieser Weg erscheint mir nicht sinnvoll. Er wirft mir außerdem folgenden Fehler:
[CODE lang="java" title="CastException"]Exception in thread "main" java.lang.ClassCastException: class nh.Panel$1 cannot be cast to class java.awt.event.KeyListener (nh.Panel$1 is in module snakeVeronikaNH of loader 'app'; java.awt.event.KeyListener is in module java.desktop of loader 'bootstrap')
at snakeVeronikaNH/nh.Panel.<init>(Panel.java:42)
at snakeVeronikaNH/nh.Frame.<init>(Frame.java:10)
at snakeVeronikaNH/nh.Main.main(Main.java:7)[/CODE]

Wie darf ich deinen Hinweis deuten?
Der Listener hat schließlich den Adapter übergeben bekommen.
Ist mein Ansatz vielleicht doch nicht so verkehrt?

LG J
 
Du kannst einen Actionlistener nicht zu einem Keylistener casten, das sind zwei recht verschiedene Klassen.

Der ActionListener ist nur dazu da, um das Auslösen eines Buttons zu melden oder die Bestätigung der Eingabe in einem Textfeld, unabhängig davon ob dies per Maus oder Tastatur passiert.

Ich denke, für das, was du da vorhast, ist ein Actionlistener grundsätzlich nicht geeignet.
 
Also nur um noch einmal paar dinge klar zu stellen:

a) Du ast einen ActionListener implementiert:
Java:
public class Panel extends JPanel implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        // ...
    }
}

Damit wäre eine Instanz von Panel auch ein ActionListener und könnte als solcher verwendet werden. Dazu müsste aber diese Instanz irgend wo, wo ein ActionListener angegeben werden müsste, angegeben werden. Also wie @Neumi5694 schon sagte: z.B. bei einem Button.

Du gibst es aber nirgends an, daher wird es auch nie aufgerufen!

Diese Stelle:
Java:
        this.addKeyListener(new Adapter(snake,this));
fügt dem Panel ein KeyListener hinzu. Und zwar eine neue Instanz von Adapter, die da extra hierfür erzeugt wird. Das hat nichts, aber auch gar nichts, mit dem ActionListener oder dem actionPerformed zu tun.
 
ok Danke an euch! Das verstehe ich soweit.
Dann wäre es doch an der Stelle jetzt für mich relevant, dem Panel einen ActionListener zuzuweisen, der auf sämtliche Tastatureingaben reagiert.
Also immer wenn eine Taste gedrückt wird, dann mach das!
[CODE lang="java" title="Versuch den ActionListener einzubinden"]public Panel() {
random = new Random();
snake = new Snake();
this.setPreferredSize(new Dimension(screenWidth, screenHeight));
this.setBackground(Color.BLACK);
this.setFocusable(true);
this.addKeyListener(new Adapter(snake, this));
this.addActionListener
this.addActionListener(new KeyListener()
{
public void keyPressed(ActionEvent e)
{

}

@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}

@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub

}

@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}
});
startGame();

}


[/CODE]
Ich habe jetzt folgende Seite besucht:
ActionListener Beispiele

Aber von den Umsetzungen klappt garnix.
Und damit lautet die eigentliche Frage: "Wie adde ich einen ActionListener zu meinem JPanel der auf sämtliche Eingaben reagiert"
Ziel der Aktion ist es, nach jeder Eingabe den Screen zu repainten.
Wenn mein Ansatz nicht korrekt ist, würde ich mich sehr über Tipps freuen, die eine Alternative zu
meiner Umsetzung darstellen.
Aktuell:
Panel erzeugt die Snake.
Snake hat ein Headobjekt welches auch eine Richtung hat "Enum dir" Körper folgt dem Head.
AdapterKlasse erkennt KeyBoardEingaben und passt somit die Richtung des Kopfes an (Dir.dir = Left, Right usw)
PanelKlasse stellt Bewegung dar, je nach Direction des Snakeheads.
[CODE lang="java" title="Beispielcode für die Bewegung"]public void move() {
System.out.println("moved");
int posX=snake.getHead().getPosX();
int posY = snake.getHead().getPosY();

if (running == true) {
while(running==true)
{
if(snake.getHead().getDirection()==dir.Right)
{
snake.getHead().setPosX(snake.getHead().getPosX()+snakesize);
}
else if(snake.getHead().getDirection()==dir.Left)
{
snake.getHead().setPosX(snake.getHead().getPosX()-snakesize);

}
else if(snake.getHead().getDirection()==dir.Up)
{
snake.getHead().setPosY(snake.getHead().getPosX()+snakesize);

}
else if(snake.getHead().getDirection() == dir.Down)
{
snake.getHead().setPosY(snake.getHead().getPosY()-snakesize);

}
//Body follow
repaint();
}
}

}[/CODE]
Vielen Dank im Voraus,
J
 
ok Danke an euch! Das verstehe ich soweit.
Dann wäre es doch an der Stelle jetzt für mich relevant, dem Panel einen ActionListener zuzuweisen, der auf sämtliche Tastatureingaben reagiert.
J
Wie gesagt, ein ActionListener macht das nicht, ActionListener reagieren auf das Aktivieren von Buttons usw.
Um auf eine Tastatureingabe zu reagieren, brauchst du einen Keylistener (die Methodennamen keyPressed, keyReleased, keyTyped ... sollten den notwendigen Hinweis liefern).
Und der funktioniert auch nur so lange die Komponente den Fokus hat, welcher der Listener zugewiesen wurde.

Da ein Panel im Normalfall aber nie den Fokus hat (den hat immer eine Komponente auf dem Panel), musst du einen ganz anderen Weg gehen. Der richtige Weg dürfte über die ActionMap/InputMap des Panels oder des Frames führen.
Hier kannst du auf Tastatureingaben reagieren, unabhängig davon, welche Komponente des Panels oder Frames gerade den Fokus hat.
Java:
InputMap inputMap = frame.getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
//JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
//JComponent.WHEN_IN_FOCUSED_WINDOW;
//JComponent.WHEN_FOCUSED;

Du musst zuerst Aktionen definieren (ActionMap), dann die Keys dieser Aktionen bestimmten Events in der InputMap zuweisen.

Hier gibt's ein Beispiel, wie so was funktioniert
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben