web-dev-qa-db-fra.com

Comment utiliser KeyListener avec JFrame?

Donc, j'essayais de déplacer un rectangle avec un KeyEvent (KeyListener) et chaque fois que j'essaie d'appuyer sur la touche, le rectangle ne bouge pas.

Le rectangle est dessiné, mais chaque fois que j'appuie sur les touches left et right, rien ne se passe. J'ai deux classes, l'une est ma classe principale avec les événements keyEvents et le cadre et l'autre, dessine le rectangle et détient la fonction pour déplacer le rectangle.

Voici mon code:

import Java.awt.event.KeyEvent;
import Java.awt.event.KeyListener;

import javax.swing.JFrame;


public class mainFrame extends JFrame implements KeyListener{

mainDraw Draw = new mainDraw();

public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    if(key == KeyEvent.VK_D){

        Draw.moveRight();
    }
}

public void keyReleased(KeyEvent e) {


}
public void keyTyped(KeyEvent e) {}

public mainFrame()
{
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
}

public static void main(String[] args) {

    mainFrame M1 = new mainFrame();

    mainDraw Draw = new mainDraw();

    JFrame frame = new JFrame("Square Move Practice");


    //frame
    frame.setVisible(true);
    frame.setResizable(false);
    frame.setSize(600, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(Draw);

}
}

Et maintenant la deuxième classe:

import Java.awt.Color;
import Java.awt.Graphics;

import javax.swing.JComponent;

public class mainDraw extends JComponent{

public int x = 50;
public int y = 50;

public void Paint(Graphics g){

    g.drawRect(x, y, 50, 50);
    g.fillRect(x, y, 50, 50);
    g.setColor(Color.BLACK);
}

public void moveRight()
{
    x = x + 5;
    y = y + 0;
    repaint();
}

}

Veuillez me dire comment je peux déplacer le rectangle. Merci d'avance!

12
user3183679

Le rectangle ne bouge pas car vous n'utilisez pas correctement JFrame. Vous devez affecter frame à new mainFrame() au lieu d'ignorer l'objet mainFrame instancié.

Il y a plusieurs autres problèmes comme le souligne @MadProgrammer.

Voici le code qui résout certains des problèmes:

mainFrame.Java

import Java.awt.*;
import Java.awt.event.KeyEvent;
import Java.awt.event.KeyListener;
import javax.swing.JFrame;


public class mainFrame extends JFrame implements KeyListener{
    private mainDraw draw;

    public void keyPressed(KeyEvent e) {
        System.out.println("keyPressed");
    }

    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode()== KeyEvent.VK_RIGHT)
            draw.moveRight();
        else if(e.getKeyCode()== KeyEvent.VK_LEFT)
            draw.moveLeft();
        else if(e.getKeyCode()== KeyEvent.VK_DOWN)
            draw.moveDown();
        else if(e.getKeyCode()== KeyEvent.VK_UP)
            draw.moveUp();

    }
    public void keyTyped(KeyEvent e) {
        System.out.println("keyTyped");
    }

    public mainFrame(){
        this.draw=new mainDraw();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                mainFrame frame = new mainFrame();
                frame.setTitle("Square Move Practice");
                frame.setResizable(false);
                frame.setSize(600, 600);
                frame.setMinimumSize(new Dimension(600, 600));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().add(frame.draw);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

mainDraw.Java

import Java.awt.Color;
import Java.awt.Graphics;
import javax.swing.JComponent;

public class mainDraw extends JComponent {

    public int x = 50;
    public int y = 50;

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawRect(x, y, 50, 50);
        g.fillRect(x, y, 50, 50);
        g.setColor(Color.BLACK);
    }

    public void moveRight() {
        x = x + 5;
        repaint();
    }

    public void moveLeft() {
        x = x - 5;
        repaint();
    }

    public void moveDown() {
        y = y + 5;
        repaint();
    }

    public void moveUp() {
        y = y - 5;
        repaint();
    }
}

BTW, utilisez SwingUtilities pour mettre le code de mise à jour de l'interface utilisateur car les objets swing ne sont pas thread-safe.

7
user508434

Il y a au moins trois problèmes ...

D'abord...

Votre classe mainFrameextends à partir de JFrame, mais dans votre méthode main, vous en créez une instance et l'ignorez, en créant votre propre JFrame.

KeyListener est enregistré dans l'instance de mainFrame, ce qui signifie qu'il a été ignoré.

Vous devriez vous débarrasser de extends JFrame car cela ne fait qu'embrouiller le problème

Deuxièmement...

KeyListener ne répondra aux événements clés que lorsque le composant auquel il est enregistré est focalisable ET a une focalisation directe, ce qui le rend peu fiable.

Au lieu de cela, vous devez utiliser API de liaisons de touches avec le panneau Draw, cela vous permettra de surmonter les problèmes de focus.

Troisièmement...

Vous avez cassé la chaîne Paint, cela signifie que lorsque le rectangle se déplace, ce qui a été peint précédemment restera.

Vous devez vous abstenir de remplacer Paint et utiliser à la place paintComponent. Il y a beaucoup de raisons à cela, mais généralement, il peint en arrière-plan, est appelé comme mises à jour des composants enfants.

Enfin, assurez-vous d'appeler super.paintComponent avant de faire quoi que ce soit d'autre, pour vous assurer que le contexte Graphics est préparé pour la peinture

Jetez un œil à Exécution d'une peinture personnalisée pour plus de détails

6
MadProgrammer