简体   繁体   中英

repaint() suddenly doesn't work

I've made about 30 different google searches and didn't come up with an answer, so I came here. So I'm trying to move the player's rectangle (the black square) left and right across the screen. It worked fine when I used regular graphics, but now that I'm using Graphics2D the repaint() seems to do nothing (ie when you press the left and right arrow keys, the rectangle doesn't move).

import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class boxface extends JComponent implements KeyListener {

  private boxobj obj;

  private int x=0, y=650;

  public void keyPressed(KeyEvent e) {
    if(e.getKeyCode()== KeyEvent.VK_RIGHT)
      moveRight();
    else if(e.getKeyCode()== KeyEvent.VK_LEFT)
      moveLeft(); }
  public void keyReleased(KeyEvent e) {}
  public void keyTyped(KeyEvent e) {}

  Rectangle player = new Rectangle(x, y, 50, 50);
  Rectangle floor = new Rectangle(0, 700, 750, 700);

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g.setColor(Color.GREEN);
    g2.fill(floor);
    g.setColor(Color.BLACK);
    g2.fill(player); }

  public void moveLeft() {
    if(x > 0) {
      x -= 50;
      repaint(); }}

  public void moveRight() {
    if(x < 700) {
      x += 50;
      repaint(); }}

  public boxface(){
    this.obj=new boxobj();
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false); }

  public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setBounds(400, 200, 756, 779);
        f.setMinimumSize(new Dimension(756, 0));
        f.setResizable(false);
        f.getContentPane().add(new boxface());
        f.setVisible(true);

      }

    });

    final java.util.Timer tmr = new java.util.Timer();
    tmr.scheduleAtFixedRate(new TimerTask()
    {
      public void run()
      {
        System.out.println("A second has passed.");

        /* the idea is that I could make a square with random
         * dimensions (within a certain limit), so that every
         * time the timer loops, a new, random square is made.
         * I just can't seem to move the rectangles using
         * repaint(); because they're Graphics2D rectangles,
         * and I can't find a way around this.
         * 
         * An example of this can be shown if you run this
         * code; the "player" rectangle cannot be moved, even
         * though keylistener is picking up inputs and the
         * rectangle's co-ordinates are being changed. In
         * other words, repaint(); isn't doing anything. */



      }
    },0,1000);

  }//end main

}//end class

Also, the "boxobj" class is just an empty class right now. It's where I plan to put the initialization of the random rectangles. I'll just put it in here for easy copy-paste.

public class boxobj {

}

The problem is that you're updating the x variable, but painting the player object.

When you construct player (via Rectangle player = new Rectangle(x, y, 50, 50); ) it takes a copy of the value of x at the time that line is executed. Since you're declaring and initializing at the same time, we know that x is zero so player will be instantiated with (0, 650, 50, 50) .

Later on, the user hits the right arrow key and your event listener fires. This increases x to 50 and calls repaint but, importantly, does not update the player object at all. When the paintComponent method gets called by the painting system player is still (0, 650, 50, 50) .

Essentially x and y record the player's position, but you're using the player object to draw the player and those variables are not getting updated in tandem.

The best way to correct this is to store the player's position in exactly one place. You can either keep x and y and modify your paintComponent method to use those, or you could throw away those two variables and modify the player object instead (with player.setLocation ). Either way will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM