Please excuse the possible simiplicity of this question. I'm revisiting Java to teach it to younger kids and also never had much experience with Graphics in the past. I also don't have an IDE available to run this code or debug at the moment, so I'm wondering if someone could help me understand conceptually what is the correct code I should write to extend the program.

There is a sample program below which should run fine. I just need to extend it by adding a few more keystroke capabilities(like stated in the program instructions/comments) as well as make sure the ball goes to the edge of the screen but is still completely visible.

Please let me know if I'm adding the extra keystroke capabilities correctly or how close or far I am. I was thinking of adding the following lines of code in the keyPressed(KeyEvent e) method.

...

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);    
}

.

I'm not completely sure how the code within the if-else blocks (above and below) should be in order to update the characteristics of the ball. Part of the reason is because I may not have a firm understanding of repaint() and paint(Graphics g). Any insights or tips are much appreciated.

.

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);
    }
}
有帮助吗?

解决方案

That seems correct at a glance (though I also do not work with graphics frequently).

Note that if you were to release the key your ovals may disappear from the screen at the next redraw.

You can create a simple Oval wrapper class to store details like the x, y, width, and height, and put those Ovals into a list that is an instance variable of your KeyListenerDemo.

Your if-blocks would be something akin to:

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);
}

At the public void paint(Graphics g) method you'd loop through the list and (re)draw those ovals.

Edit: I'd implement the oval class like:

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;
   }


}

The list is simply declared as protected List<Oval> ovals = new LinkedList<>();, right above your main method. To loop over it (in your paint method, where g is available, you can use:

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

Hopefully this helps!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top