Ключевые события в Java - Справка для начинающих - PullRequest
0 голосов
/ 15 сентября 2010

Итак, я работал над простой программой, изучая Java, которая выводит на экран небольшой прямоугольный экран, на котором движется круг.Фон и круг также меняют цвета и скорости.

Теперь я пытаюсь добавить KeyEvents, чтобы при вводе символа круг изменял направление.Я уже несколько часов пытаюсь разобраться с функцией KeyEvent, и я застрял.

Как бы вы изменили следующий код, чтобы программа реагировала на ввод с клавиатуры:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.JFrame;

public class MovingCircle3 extends JFrame implements ActionListener {

    Ellipse2D.Double myEllipse;
    Rectangle2D.Double backgroundRectangle;
    private int paintTally = 0;     // Counts # of repaints.
    private int timerSpeed = 500;   // Holds speed of timer. Initially: 500ms.
    private Timer timerOjbect;
    private char shapeMoveInput = 'd';

    public MovingCircle3() {
        myEllipse = new Ellipse2D.Double(30, 30, 20, 20); // Ellipse starting point
        backgroundRectangle = new Rectangle2D.Double(0, 0, 400, 300); // Background.
        this.timerOjbect = new Timer(500, this);
        timerOjbect.start();                 //Creates and starts timer.
    }

    public static void main(String[] args) {
        System.out.print("Game Controls: \n  l = Move left. \n  r = Move right. \n  u = Move up. \n  d = Move down. \n    ENTER COMMAND: ");    // Game controls.

        MovingCircle3 b = new MovingCircle3();

        b.setVisible(true);
        b.setSize(400, 300);
        b.setVisible(true);
        b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void keyPressed(KeyEvent e) {
        try {
            shapeMoveInput = e.getKeyChar();
        } catch (Exception ex) {
            shapeMoveInput = 'd';
        }
    }

    public void actionPerformed(ActionEvent ae) {
        //This will be called by the Timer
        if (shapeMoveInput == 'l') {
            myEllipse.setFrame(myEllipse.getX() - 1, myEllipse.getY(), myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 x-pixel left 
        } else if (shapeMoveInput == 'r') {
            myEllipse.setFrame(myEllipse.getX() + 1, myEllipse.getY(), myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 x-pixel right
        } else if (shapeMoveInput == 'u') {
            myEllipse.setFrame(myEllipse.getX(), myEllipse.getY() - 1, myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 y-pixel up
        } else if (shapeMoveInput == 'd') {
            myEllipse.setFrame(myEllipse.getX(), myEllipse.getY() + 1, myEllipse.getWidth(), myEllipse.getHeight());   //Move 1 y-pixel
        }
        repaint();
    }

    public void paint(Graphics g) {
        paintTally++; // Increments by one for every repaint().
        if (paintTally % 25 == 0) { // Take modulus 25 of paintTally to execute every 25 paints.
            timerSpeed = (int) (timerSpeed / 2);
            timerOjbect.setDelay(timerSpeed); // Divide speed by 2 and see to timer length.  
        }
        int isPaintTen = (int) (paintTally / 10);  // Divide current count by 10.
        Graphics2D g2 = (Graphics2D) g;
        if ((isPaintTen % 2) == 0) { // Take modulus to set if #/10 is odd or even.
            g2.setColor(Color.YELLOW);
            g2.fill(backgroundRectangle);
            g2.setColor(Color.RED);
            g2.draw(myEllipse);

        } else if ((isPaintTen % 2) == 1) {
            g2.setColor(Color.RED);
            g2.fill(backgroundRectangle);
            g2.setColor(Color.YELLOW);
            g2.draw(myEllipse);
        }
    }
}

Ответы [ 3 ]

2 голосов
/ 15 сентября 2010

1) Вы никогда не должны (если вы действительно не знаете, что делаете) переопределять метод рисования JFrame. Настраиваемое рисование выполняется путем переопределения метода paintComponent (...) для JPanel. Затем вы добавляете пользовательскую панель в JFrame. Вам дали ссылку на учебник по Swing в комментариях к вашей первоначальной публикации. Прочтите раздел «Custom Painting» для получения дополнительной информации и рабочих примеров.

2) Затем вам нужно будет добавить KeyListener на панель. Однако KeyEvents передаются только компоненту с фокусом, поэтому вам нужно сделать панель фокусируемой, используя метод setFocusable (...) на панели.

Однако KeyListener не является правильным способом решения этой проблемы. Вы должны использовать привязки клавиш, которые гораздо более гибки, чем использование KeyListeners. Опять же, в руководстве Swing есть раздел «Как использовать привязки клавиш».

1 голос
/ 15 сентября 2010

Читать дальше InputMap и ActionMap. (учебное пособие здесь ) Это двухэтапный процесс сопоставления нажатий клавиатуры с идентификатором, а затем идентификаторами при вызове метода.

1 голос
/ 15 сентября 2010

Эй, может показаться, что вам нужен KeyListener, но ActionListener будет работать на вашем JFrame.Похоже, что вы реализуете ActionListener, который является суперклассом ключевого слушателя.Вы реализуете это правильно, но после этого вам нужно зарегистрировать нового слушателя, это заставляет поток событий в Swing отправлять события этому слушателю.Поток событий является потоком, управляемым системой.Вы можете прочитать эту ветку событий на веб-сайте Oracle / Suns.Также просто примечание, которое использует паттерн наблюдателя, если вам интересно.

Все, что вам нужно сделать, - это инициализировать. MovingCircle3 () сделать следующее:

this.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
                movingcircle3_Function(e);
            }
        });  

, или вы можете попробовать следующеено я не уверен, что это будет работать правильно

this.addActionListener(this);

...