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 (i.e. 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.