java obsługa klawiatury jpanel

0

witam, chce zaprogramować grę Sokoban, na tą chwile gra składa się z 3 klas, mam problem z implementacją klasy odpowiadającej za poruszanie się, chciałem się dowiedzieć czemu metoda addKeyListener zawierająca się w metodzie ruch() odpowiadająca za obsługę klawiatury nie jest wywoływana?? tworze referencje do tej klasy i w konstruktorze ją wywołuje ale ta metoda nie jest wywoływana. bardzo proszę o wskazanie błędu ;) i przepraszam za chaotyczne opisanie problemu. o to kod:

 /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaswingsokoban;

import javax.swing.SwingUtilities;

/**
 *
 * @author admin
 */
public class JavaSwingSokoban {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ClassBoard classBoard = new ClassBoard();
            }
        });
    }
}

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaswingsokoban;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 *
 * @author marcin kaszuba
 */
public class ClassBoard extends JFrame{

    private int widthWindow = 660;
    private int heightWindow = 500;
    private int sizeSquare = 40;
    private int positionX = 50;
    private int positionY = 50;
    JPanel jPanel = new JPanel();
    ClassMove classMove = new ClassMove();
    int defaultPositionX = 2;
    int defaultPositionY = 6;
    int tmp = 0;
    //0 - mur czarny
    //1 - puste pole bialy
    //2 - pudelko zielony
    //3 - ludzik czerwony
    static int[][] plansza = {
        {0,0,0,0,0,0,0,0,0,0,0,0,1,1},
        {0,1,1,1,1,0,1,1,1,1,1,0,0,0},
        {0,1,1,1,1,0,1,2,1,1,2,1,1,0},
        {0,1,1,1,1,0,2,0,0,0,0,1,1,0},
        {0,1,1,1,1,1,1,1,1,0,0,1,1,0},
        {0,3,1,1,1,0,1,0,1,1,2,1,0,0},
        {0,0,0,0,0,0,1,0,0,2,1,2,1,0},
        {1,1,0,1,2,1,1,2,1,2,1,2,1,0},
        {1,1,0,1,1,1,1,0,1,1,1,1,1,0},
        {1,1,0,0,0,0,0,0,0,0,0,0,0,0}
    };

    public ClassBoard() {
        setTitle("sokoban !!!!");
        setLocation(new Point(100, 100));
        setSize(new Dimension(widthWindow, heightWindow));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);

        add(jPanel);

        revalidate();
        classMove.ruch();
    }

    @Override
    public void paint(Graphics graphics){
        drawBoard(graphics);
    }

    void drawBoard(Graphics graphics){
        super.paint(graphics);
        for(int i = 0; i < plansza.length; ++i){
            for(int j = 0; j < plansza[0].length; ++j){
                if(plansza[i][j] == 0){
                    graphics.setColor(Color.BLACK);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 1){
                    graphics.setColor(Color.WHITE);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 2){
                    graphics.setColor(Color.GREEN);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 3){
                    graphics.setColor(Color.RED);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);                    
                }
            }
        }
    }

}

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaswingsokoban;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;

/**
 *
 * @author marcin
 */
public class ClassMove extends JPanel{

    public void ruch(){
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent keyEvent){
                switch(keyEvent.getKeyCode()){
                    case KeyEvent.VK_UP:
                        System.out.println("wcisles up");
                        break;
                    case KeyEvent.VK_DOWN:
                        System.out.println("wcisles down");
                        break;
                    case KeyEvent.VK_LEFT:
                        System.out.println("wcisles left");
                        break;
                    case KeyEvent.VK_RIGHT:
                        System.out.println("wcisles right");
                        break;
                }
            }
        });
    }
}

pomyliłem się, sprawdziłem dokładniej i nie jest wywoływana metoda keyPressed w new KeyAdapter(), proszę o pomoc

0

Z tego co wiem, po "case" mogą pojawiać się tylko liczby, np. "case 1:". Stwórz nową zmienną i użyj IF, by do każdego klawisza przyporządkować inną liczbę, później zrób switch(nazwa zmiennej) i po "case" dawaj liczby możliwe do przyporządkowania w IF, np.:

int key;
if (keyEvent.getKeyCode == KeyEvent.VK_UP) key = 1;
else if (keyEvent.getKeyCode == KeyEvent.VK_DOWN) key = 2;
else if (keyEvent.getKeyCode == KeyEvent.VK_LEFT) key = 3;
else if (keyEvent.getKeyCode == KeyEvent.VK_RIGHT) key = 4;
switch(key){
                    case 1:
                        System.out.println("wcisles up");
                        break;
                    case 2:
                        System.out.println("wcisles down");
                        break;
                    case 3:
                        System.out.println("wcisles left");
                        break;
                    case 4:
                        System.out.println("wcisles right");
                        break;
                }

Od razu mówię, że nie testowałem tego kodu, więc niczego nie gwarantuję.

0

Po wstępnej analizie, wydaje mi się że po prostu nie dodajesz classMove do formatki. Swoją drogą, jPanel chyba jest zbędny.

0

JPanel zawiera metodę addKeyListener()

0
mar-kasz napisał(a):

JPanel zawiera metodę addKeyListener()

Fajnie że zawiera taką metodę, ale skoro z niego nie korzystasz nie jest ci potrzebny...

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

public class ClassBoard extends JFrame {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                ClassBoard classBoard = new ClassBoard();
            }
        });
    }

    private int widthWindow = 660;
    private int heightWindow = 500;
    private int sizeSquare = 40;
    private int positionX = 50;
    private int positionY = 50;
    int defaultPositionX = 2;
    int defaultPositionY = 6;
    int tmp = 0;
    //0 - mur czarny
    //1 - puste pole bialy
    //2 - pudelko zielony
    //3 - ludzik czerwony
    static int[][] plansza = {
        {0,0,0,0,0,0,0,0,0,0,0,0,1,1},
        {0,1,1,1,1,0,1,1,1,1,1,0,0,0},
        {0,1,1,1,1,0,1,2,1,1,2,1,1,0},
        {0,1,1,1,1,0,2,0,0,0,0,1,1,0},
        {0,1,1,1,1,1,1,1,1,0,0,1,1,0},
        {0,3,1,1,1,0,1,0,1,1,2,1,0,0},
        {0,0,0,0,0,0,1,0,0,2,1,2,1,0},
        {1,1,0,1,2,1,1,2,1,2,1,2,1,0},
        {1,1,0,1,1,1,1,0,1,1,1,1,1,0},
        {1,1,0,0,0,0,0,0,0,0,0,0,0,0}
    };

    public ClassBoard() {
        setTitle("sokoban !!!!");
        setLocation(new Point(100, 100));
        setSize(new Dimension(widthWindow, heightWindow));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);

//        add(jPanel);

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent keyEvent){
                switch(keyEvent.getKeyCode()){
                    case KeyEvent.VK_UP:
                        System.out.println("wcisles up");
                        break;
                    case KeyEvent.VK_DOWN:
                        System.out.println("wcisles down");
                        break;
                    case KeyEvent.VK_LEFT:
                        System.out.println("wcisles left");
                        break;
                    case KeyEvent.VK_RIGHT:
                        System.out.println("wcisles right");
                        break;
                }
            }
        });

        revalidate();
    }

    @Override
    public void paint(Graphics graphics){
        drawBoard(graphics);
    }

    void drawBoard(Graphics graphics){
        super.paint(graphics);
        for(int i = 0; i < plansza.length; ++i){
            for(int j = 0; j < plansza[0].length; ++j){
                if(plansza[i][j] == 0){
                    graphics.setColor(Color.BLACK);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 1){
                    graphics.setColor(Color.WHITE);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 2){
                    graphics.setColor(Color.GREEN);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 3){
                    graphics.setColor(Color.RED);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                }
            }
        }
    }

}
0

poprawiłem kod i działa już obsługa klawiatury w osobnej klasie, przerobiłem klasę ClassMove i w klasie ClassBoard w konstruktorze dodałem this.addKeyListener(classMove); , o to kod zmieniony:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaswingsokoban;

import javax.swing.SwingUtilities;

/**
 *
 * @author admin
 */
public class JavaSwingSokoban {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ClassBoard classBoard = new ClassBoard();
            }
        });
    }
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaswingsokoban;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 *
 * @author marcin kaszuba
 */
public class ClassBoard extends JFrame{

    private int widthWindow = 660;
    private int heightWindow = 500;
    private int sizeSquare = 40;
    private int positionX = 50;
    private int positionY = 50;
    JPanel jPanel = new JPanel();
    ClassMove classMove = new ClassMove();
    int defaultPositionX = 2;
    int defaultPositionY = 6;
    int tmp = 0;
    //0 - mur czarny
    //1 - puste pole bialy
    //2 - pudelko zielony
    //3 - ludzik czerwony
    static int[][] plansza = {
        {0,0,0,0,0,0,0,0,0,0,0,0,1,1},
        {0,1,1,1,1,0,1,1,1,1,1,0,0,0},
        {0,1,1,1,1,0,1,2,1,1,2,1,1,0},
        {0,1,1,1,1,0,2,0,0,0,0,1,1,0},
        {0,1,1,1,1,1,1,1,1,0,0,1,1,0},
        {0,3,1,1,1,0,1,0,1,1,2,1,0,0},
        {0,0,0,0,0,0,1,0,0,2,1,2,1,0},
        {1,1,0,1,2,1,1,2,1,2,1,2,1,0},
        {1,1,0,1,1,1,1,0,1,1,1,1,1,0},
        {1,1,0,0,0,0,0,0,0,0,0,0,0,0}
    };

    public ClassBoard() {
        setTitle("sokoban !!!!");
        setLocation(new Point(100, 100));
        setSize(new Dimension(widthWindow, heightWindow));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);

        add(jPanel);

        revalidate();
        this.addKeyListener(classMove);
    }

    @Override
    public void paint(Graphics graphics){
        drawBoard(graphics);
    }

    void drawBoard(Graphics graphics){
        super.paint(graphics);
        for(int i = 0; i < plansza.length; ++i){
            for(int j = 0; j < plansza[0].length; ++j){
                if(plansza[i][j] == 0){
                    graphics.setColor(Color.BLACK);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 1){
                    graphics.setColor(Color.WHITE);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 2){
                    graphics.setColor(Color.GREEN);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);
                } else if(plansza[i][j] == 3){
                    graphics.setColor(Color.RED);
                    graphics.fillRect((sizeSquare * j) + positionX, (sizeSquare * i) + positionY, sizeSquare, sizeSquare);                    
                }
            }
        }
    }

}

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaswingsokoban;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

/**
 *
 * @author marcin
 */
public class ClassMove implements KeyListener{

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent keyEvent) {
        switch(keyEvent.getKeyCode()){
            case KeyEvent.VK_UP:
                System.out.println("wcisles up");
                break;
            case KeyEvent.VK_DOWN:
                System.out.println("wcisles down");
                break;
            case KeyEvent.VK_LEFT:
                System.out.println("wcisles left");
                break;
            case KeyEvent.VK_RIGHT:
                System.out.println("wcisles right");
                break;
        }
    }

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

@norbi452 Piszesz dobrze a zarazem robisz głupoty - jestem ciekawy czy dojdziesz dlaczego tak uważam jeżeli skieruje cię do strony oracla z opisem klasy KeyEvent:>
http://docs.oracle.com/javase[...]/java/awt/event/KeyEvent.html <- zapraszam do rozkminy

jak dobrze widzę tego swojego listenera dodajesz na Panel - jest opcja, że panel nie ma focusa a on musi być, żeby przyjmować eventy klawiatury(btw - na pewno tak jest, sam panel nie jest chyba nawet focusable - gdzieś z @bogdans chyba o tym jakieś wywody prowadziłem, możesz sprawdzić)

O wiele lepiej jest założyć coś w stylu global hooka na klawiature (ale spokojnie, w javie;]) ale uwaga, wtedy będziesz wyłapywał wszystkie eventy.
Akurat ja w aplikacji to robie tak

    static {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {

            private KeyStroke secretKeystroke = KeyStroke.getKeyStroke("shift A"); // tutaj 

            @Override
            public boolean dispatchKeyEvent(KeyEvent ke) {  // tutaj dostaniesz dowolny event klawiatury wykonany w aplikacji
                if (KeyStroke.getKeyStrokeForEvent(ke) == secretKeystroke) { // 
                    logger.log(Level.FINE,"Wciśnięto keystroke: "+secretKeystroke);
                    consoleDialog.setVisible(true);
                }
                return false;
            }
        });
    }
0

o co chodzi z metodą setFocusable()?? jPanel mogę ustawić na true?? ale po co?? gdy ustawiam jPanel.setFocusable(true); to przestaje dzialac moja implementacja obsługi klawiatury w klasie ClassMove.

0

Umożliwienie komponentowi przechwytywania eventów z klawiatury.
http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html

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