KeyListener nie współpracuje. Nieprawidłowości z focusem?

0

Cześć wszystkim.
Niedawno zacząłem uczyć się Javy i do tej pory szło dość gładko.
Chciałem napisać aplikację, w której przesuwałbym przycisk po ekranie wykorzystując strzałki klawiatury. Problem w tym, że program nie przechwytuje zdarzeń klawiatury.

Wiem, że pastacode, ale estetyka pisania w javie przyjdzie mi z czasem.
Klasa Test:

import java.awt.EventQueue;

class Test {
	public static void main(String[] args) {
			
		EventQueue.invokeLater(new Runnable() {

			public void run() {
				new ActionFrame();
			}
			
		});
	}
}

Klasa ButtonPanel:

import java.awt.*;

import javax.swing.JButton;
import javax.swing.JPanel;

public class ButtonPanel extends JPanel {
	
	public static final int HEIGHT = 480;
	public static final int WIDTH = 640;
	private JButton button;
	
	private int x = 100, y = 100;
	
	public ButtonPanel() {
		button = new JButton("o");
		
		button.setLocation(x, y);
		button.setSize(50, 50);
		
		setLayout(null);
		setPreferredSize(new Dimension(WIDTH, HEIGHT));
		add(button);
	}
	public void MoveUp() {
		y += 50;
		button.setLocation(x, y);
	}
	
	public void MoveDown() {
		y -= 50;
		button.setLocation(x, y);
	}
	
	public void MoveLeft() {
		x -= 50;
		button.setLocation(x, y);
	}
	
	public void MoveRight() {
		x += 50;
		button.setLocation(x, y);
	}
}

Klasa Keyboard:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JPanel;

public class Keyboard extends JPanel implements KeyListener {
	
	JPanel buttonPanel = new ButtonPanel();
	
	public Keyboard() {
		setPreferredSize(new Dimension(WIDTH, HEIGHT));
		addKeyListener(this);
		setFocusable(true);
	}
	
	public void keyPressed(KeyEvent event) {
		if(event.getKeyCode() == event.VK_UP ) {
			((ButtonPanel) buttonPanel).MoveUp();
		}
		
		else if(event.getKeyCode() == event.VK_DOWN ) {
			((ButtonPanel) buttonPanel).MoveDown();
		}
		
		else if(event.getKeyCode() == event.VK_LEFT ) {
			((ButtonPanel) buttonPanel).MoveLeft();
		}
		
		else if(event.getKeyCode() == event.VK_RIGHT ) {
			((ButtonPanel) buttonPanel).MoveRight();
		}
	}
	
	public void keyReleased(KeyEvent event) {
		
	}
	
	public void keyTyped(KeyEvent event) {
		
	}

}

Klasa ActionFrame:

import java.awt.*;

import javax.swing.*;

public class ActionFrame extends JFrame {
	
	public ActionFrame() {
		super("Test akcji");
		
		JPanel buttonPanel = new ButtonPanel();
		JPanel keyboard = new Keyboard();
		
		add(keyboard);
		add(buttonPanel);

		keyboard.requestFocus();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		setVisible(true);
	}
}

Byłbym bardzo wdzięczny, gdyby ktoś mi z tym pomógł.

Pozdrawiam,
Grzegorz

0

Może jakieś repaint po przesunięciu przycisku.

0

Już próbuję. Dodam tylko, że wcześniej zrobiłem coś takiego tyle tylko, że sterowane było przyciskami wygenerowanymi w aplikacji i działało dobrze. Nie potrzebowało repaint()'a.

@Edit:

repaint nic nie daje, ale:
Dodałem funkcje println do funkcji MoveUp, MoveDown, MoveLeft i MoveRight tak, aby wypisało w konsoli która z funkcji została wywołana i okazuje się, że skanowanie klawiatury działa.

1

Wiem, repaint jest chyba zbyteczne. Problem jest w tym, że masz dwa obiekty typu ButtonPanel, jeden z nich wyświetlasz a w drugim przesuwasz przycisk.

import java.awt.*;
 
import javax.swing.*;
 
public class ActionFrame extends JFrame {
 
    public ActionFrame() {
        super("Test akcji");
 
        JPanel buttonPanel = new ButtonPanel();
        JPanel keyboard = new Keyboard(buttonPanel);
...
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
 
import javax.swing.JButton;
import javax.swing.JPanel;
 
public class Keyboard extends JPanel implements KeyListener {
 
    JPanel buttonPanel = null;
 
    public Keyboard(JPanel buttonPanel) {
        this.buttonPanel = buttonPanel;

Poza tym ekranowa oś y jest skierowana w dół

    public void MoveUp() {
        y -= 50;
        button.setLocation(x, y);
    }
 
    public void MoveDown() {
        y += 50;
        button.setLocation(x, y);
    }
0

Dzięki wielkie.
Teraz działa, tylko nie jestem pewien czy zrozumiałem działanie tych linii:

 JPanel buttonPanel = null;
 
    public Keyboard(JPanel buttonPanel) {
        this.buttonPanel = buttonPanel;

Pierwsza jakby informuje tylko, że będzie obiekt typu JPanel buttonPanel, ale nie będzie używany w tej klasie(czyli jakby dla niej go nie było).
2 ostatnie linie robią jakby to samo tyle tylko, że wewnątrz konstruktora, który potem w innej klasie przyjmie obiekt typu JPanel jako argument i będzie nim operował. Czy dobrze myślę?

0

Nie bardzo, wiersz

JPanel buttonPanel = null;

deklaruje, że z jakiegoś buttonPanel klasa będzie korzystać. Kod nie przesądza czy ten buttonPanel zostanie skonstruowany, czy klasa Keyboard otrzyma referencję do już istniejącego. A w konstruktorze

    public Keyboard(JPanel buttonPanel) {
        this.buttonPanel = buttonPanel;

klasa Keyboard otrzymuje referencję do skonstruowanego gdzie indziej panelu.

0

Dziękuję za pomoc.
Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1