import java.awt.Canvas; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Toolkit; import java.awt.image.BufferStrategy; import java.awt.event.KeyEvent; import java.awt.event.KeyAdapter; import java.awt.Graphics2D; // Used for anti-aliasing import java.awt.RenderingHints; // Used for anti-aliasing import javax.swing.JFrame; import javax.swing.JPanel; public class GraphicsMoveObjectWithKeyboardAndJFrame implements Runnable { JFrame frame; Canvas canvas; BufferStrategy buffer; int width = 400, height = 400; int dotX = 190, dotY = 180, dotSize = 50; int key; boolean moveBall = false; public static void main(String[] args) { // Create a thread containing an instance of the // 'GraphicsMoveObjectWithKeyboardAndJFrame' class new Thread(new GraphicsMoveObjectWithKeyboardAndJFrame()).start(); } // Constructor public GraphicsMoveObjectWithKeyboardAndJFrame() { JFrame frame = new JFrame("Object Movement with a Keyboard on a JFrame"); JPanel panel = (JPanel) frame.getContentPane(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(width, height); frame.setLocationRelativeTo(null); frame.setResizable(false); frame.setVisible(true); // Create a new canvas, set its background color, and add it to the frame canvas = new Canvas(); canvas.setBackground(Color.BLACK); panel.add(canvas); canvas.addKeyListener(new KeyAdapter() { // This method is called whenever a key is pressed public void keyPressed(KeyEvent e) { moveBall = true; key = e.getKeyCode(); } // This method is called whenever a key is released public void keyReleased(KeyEvent e) { moveBall = false; } }); // Set up multi-buffering by creating (in this case, two) buffers that // will be used to draw and display the canvas images on the frame; // double-buffering (or multi-buffering) allows for the flicker-free // rendering (drawing) of images/animation; the 'createBufferStrategy()' // method will attempt to create the best strategy available with the // number of buffers supplied; a page-flipping strategy is attempted // first, and then a blitting strategy using accelerated buffers; if // neither of those work, an unaccelerated blitting strategy is used canvas.createBufferStrategy(2); buffer = canvas.getBufferStrategy(); // Make sure the canvas has the focus so that the user does not // have to first click on the frame before using the arrow keys canvas.requestFocus(); } public void run() { // Since a timer is not being used, this method should be set to // continuously repeat (loop); a thread is used (below) to pause // the loop, which effectively simulates a timer with an interval while (true) { if (moveBall) { if (key == KeyEvent.VK_LEFT && dotX > 22) dotX -= 4; if (key == KeyEvent.VK_RIGHT && dotX < width - 42) dotX += 4; if (key == KeyEvent.VK_UP && dotY > 28) dotY -= 4; if (key == KeyEvent.VK_DOWN && dotY < height - 52) dotY += 4; } PaintFrame(); try { // Pause for 25/1000 seconds (so that the dot does not move // around the frame too quickly Thread.sleep(25); } catch (InterruptedException e) { // This section is required when using 'Thread.sleep()' } } } public void PaintFrame() { // Prepare to create the image on a separate 'Image' instance; this // will prevent flickering while the mouse is being moved around // the frame by using a "buffer" on which the frame image will // first be drawn before it is displayed to the user Graphics graphics = buffer.getDrawGraphics(); // Erase the previous image of the dot so that the arrow keys // actually move the dot, and do not simply draw with it graphics.clearRect(0, 0, width, height); // This line causes graphics and text to be rendered with anti-aliasing // turned on, making the overall display look smoother and cleaner ((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Add the text instructions to the buffer graphics.setColor(Color.WHITE); graphics.setFont(new Font("Helvetica", Font.BOLD, 16)); graphics.drawString("Use the arrow keys to move the dot...", 56, 18); // Add the red dot in the correct location (under the mouse pointer) graphics.setColor(Color.RED); graphics.fillOval(dotX - dotSize / 2 + 7, dotY - dotSize / 2 - 2, dotSize, dotSize); // Make the next available buffered image visible on the frame, by either // changing the display pointer (flipping) or copying the memory (blitting) buffer.show(); // This line synchronizes the graphics state by flushing buffers containing // graphics events and forcing the frame drawing to happen now; otherwise, // it can sometimes take a few extra milliseconds for the drawing to take // place, which can result in jerky graphics movement; this line ensures // that the display is up-to-date; it is useful for animation, since it // reduces or eliminates flickering Toolkit.getDefaultToolkit().sync(); } }