【问题标题】:simple KeyListenerDemo.java example: Adding more keystrokes issue简单的 KeyListenerDemo.java 示例:添加更多击键问题
【发布时间】:2014-04-19 01:18:52
【问题描述】:

请原谅这个问题可能很简单。我正在重新审视 Java 以将其教给年幼的孩子,并且过去也从未有过太多的图形经验。我目前也没有可用于运行此代码或调试的 IDE,所以我想知道是否有人可以帮助我从概念上理解我应该编写什么是正确的代码来扩展程序。

下面有一个示例程序应该可以正常运行。我只需要通过添加更多击键功能(如程序指令/cmets 中所述)来扩展它,并确保球到达屏幕边缘但仍然完全可见。

请让我知道我是否正确添加了额外的击键功能或者我有多近或多远。我正在考虑在 keyPressed(KeyEvent e) 方法中添加以下代码行。

...

else if(keyCode == KeyEvent.VK_Z)
{
    g.fillOval(x + radius, y + radius, 2 * radius, 2 * radius);
}
else if(keyCode == KeyEvent.VK_S)
{
    g.fillOval(x - radius, y - radius, radius, radius);
}
else if(keyCode == KeyEvent.VK_B)
{
    g.fillOval(x - radius, y - radius, 4 * radius, 4 * radius);    
}
else if(keyCode == KeyEvent.VK_C)    
{     
   g.setColor(Color.green);    
}

.

我不完全确定 if-else 块(上方和下方)中的代码应该如何更新球的特性。部分原因是我可能对repaint()paint(Graphics g)的理解不够深入。非常感谢任何见解或提示。

.

import java.awt.*;
import java.awt.event.*;                            // #1
import javax.swing.*;   

/******************************************************************************
 * 
 * KeyListenerDemo.java
 * Demonstrates getting keyboard input using the KeyListener interface.
 * 
 * Program 18: Extend this program by adding a few more keystroke commands:
 *      z     (VK_Z)    - Cause the ball to jump to a random new location.
 *      s     (VK_S)    - Make the ball smaller - multiply its diameter 1/2.
 *      b     (VK_B)    - Make the ball bigger - multiply its diameter by 2.
 *      c     (VK_C)    - Change the color (in any way you'd like).
 *
 *  In addition, modify the program to ensure the following:
 *  - The ball goes all the way to the edge of the screen but stays
 *          completely on the screen. 
 *  - If a doubled diameter doesn't fit, make it as large as possible.
 *  - Be sure the ball never completely disappears.
 * 
 *****************************************************************************/
public class KeyListenerDemo extends JFrame
                        implements KeyListener      // #2
{
    // Class Scope Finals
    private static final int SCREEN_WIDTH = 1000;
    private static final int SCREEN_HEIGHT = 800;
    private static final int START_RADIUS = 25;
    private static final int START_X = 100;
    private static final int START_Y = 100;
    private static final int STEP_SIZE = 10;

    // Class Scope Variables
    private static int x = START_X;             // x at center of the ball
    private static int y = START_Y;             // y at center of the ball
    private static int radius = START_RADIUS;   // radius of the ball

    // Methods
    /**
     * Create the window and register this as a KeyListener
     * 
     * @param args
     */
    public static void main (String[] args)
    {
        // Set up the JFrame window.
        KeyListenerDemo gp = new KeyListenerDemo();
        gp.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        gp.setVisible(true);

        gp.addKeyListener(gp);                          // #3
        // If this class had a constructor and you moved this line into
        //   that constructor it could not refer to gp since that variable
        //   is local to this method.  Instead you would write::
        // addKeyListener(this);
    }

    /**
     * Called when a key is first pressed
     * Required for any KeyListener
     * 
     * @param e     Contains info about the key pressed
     */
    public void keyPressed(KeyEvent e)                  // #4A
    {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_LEFT)
        {
            x = x - STEP_SIZE;
        }
        else if (keyCode == KeyEvent.VK_RIGHT)
        {
            x = x + STEP_SIZE;
        }
        else if (keyCode == KeyEvent.VK_UP)
        {
            y = y - STEP_SIZE;
        }
        else if (keyCode == KeyEvent.VK_DOWN)
        {
            y = y + STEP_SIZE;
        }
        repaint();
    }

    /**
     * Called when typing of a key is completed
     * Required for any KeyListener
     * 
     * @param e     Contains info about the key typed
     */
    public void keyTyped(KeyEvent e)                    // #4B
    {
    }

    /**
     * Called when a key is released
     * Required for any KeyListener
     * 
     * @param e     Contains info about the key released
     */
    public void keyReleased(KeyEvent e)                 // #4C
    {
    }

    /**
     * paint - draw the figure
     * 
     * @param g     Graphics object to draw in
     */
    public void paint(Graphics g)
    {
        g.setColor(Color.white);
        g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

        g.setColor(Color.blue);
        g.fillOval(x - radius, y - radius, 2 * radius, 2 * radius);
    }
}

【问题讨论】:

    标签: java keylistener


    【解决方案1】:

    乍一看似乎是正确的(尽管我也不经常使用图形)。

    请注意,如果您松开按键,您的椭圆可能会在下一次重绘时从屏幕上消失。

    您可以创建一个简单的 Oval 包装类来存储 x、y、宽度和高度等详细信息,并将这些 Ovals 放入一个列表中,该列表是您的 KeyListenerDemo 的实例变量。

    您的 if 块类似于:

    else if(keyCode == KeyEvent.VK_Z)
    {
        Oval o = new Oval(x + radius, y + radius, 2 * radius, 2 * radius);
        ovals.add(o); // where ovals is an ArrayList<Oval> or LinkedList<Oval>
        g.fillOval(o.x, o.y, o.width, o.height);
    }
    

    public void paint(Graphics g) 方法中,您将遍历列表并(重新)绘制这些椭圆。

    编辑:我会像这样实现椭圆类:

    public class Oval {
       int x;
       int y;
       int width;
       int height;
       public Oval(int x, int y, int width, int height) {
           this.x = x;
           this.y = y;
           this.width = width;
           this.height = height;
       }
    
    
    }
    

    该列表被简单地声明为protected List&lt;Oval&gt; ovals = new LinkedList&lt;&gt;();,就在您的主要方法上方。要循环它(在您的绘画方法中,g 可用,您可以使用:

    for(Oval o : ovals){
        g.fillOval(o.x, o.y, o.width, o.height);
    }
    

    希望这会有所帮助!

    【讨论】:

    • 抱歉,我对此很陌生,图形体验非常有限。你的 Oval 包装类和你的 Oval 列表在代码方面会是什么样子?谢谢你的帮助。
    猜你喜欢
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 2011-08-03
    • 2011-06-15
    相关资源
    最近更新 更多