theta
asked on
How to erase a graphic object on JPanel.
I have a drawingpanel which extends from JPanel. I am trying to move objects on it. When I draw a circle and move it(draw it on a different place), I am unable to erase the last one I draw. I am using setColor(Color.white) and fillRect(..) to erase the previous drawing, but when I run my program I get all the drawings of the circle on the screen. How can I erase the panel before I draw a circle in a new position?
Theta.
Theta.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I'm attaching the source for two classes for the O'Reilly Java2D Graphics programming book that appear to demonstrate how to accomplish what you want to do using an offscreen image. All the examples from the book are available from the O'Reilly website (http://www.oreilly.com/catalog/java2d/ and click on the Examples line on the left side of the page).
---------- ApplicationFrame.java ----------
import java.awt.*;
import java.awt.event.*;
public class ApplicationFrame extends Frame {
public ApplicationFrame() {
this("ApplicationFrame v1.0");
}
public ApplicationFrame(String title) {
super(title);
createUI();
}
protected void createUI() {
setSize(500, 400);
center();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
public void center() {
Dimension screenSize = Toolkit.getDefaultToolkit( ).getScree nSize();
Dimension frameSize = getSize();
int x = (screenSize.width - frameSize.width) / 2;
int y = (screenSize.height - frameSize.height) / 2;
setLocation(x, y);
}
}
---------- SmoothMove.java ----------
import java.awt.*;
import java.awt.event.*;
public class SmoothMove extends ApplicationFrame implements MouseMotionListener {
public static void main(String[] args) {
new SmoothMove();
}
private int mX, mY;
private Image mImage;
public SmoothMove() {
super("SmoothMove v1.0");
addMouseMotionListener(thi s);
setVisible(true);
}
public void mouseMoved(MouseEvent me) {
mX = (int)me.getPoint().getX();
mY = (int)me.getPoint().getY();
repaint();
}
public void mouseDragged(MouseEvent me) {
mouseMoved(me);
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
// Clear the offscreen image.
Dimension d = getSize();
checkOffscreenImage();
Graphics offG = mImage.getGraphics();
offG.setColor(getBackgroun d());
offG.fillRect(0, 0, d.width, d.height);
// Draw into the offscreen image.
paintOffscreen(mImage.getG raphics()) ;
// Put the offscreen image on the screen.
g.drawImage(mImage, 0, 0, null);
}
private void checkOffscreenImage() {
Dimension d = getSize();
if (mImage == null ||
mImage.getWidth(null) != d.width ||
mImage.getHeight(null) != d.height) {
mImage = createImage(d.width, d.height);
}
}
public void paintOffscreen(Graphics g) {
int s = 100;
g.setColor(Color.blue);
g.fillRect(mX - s / 2, mY - s / 2, s, s);
}
}
I hope this helps.
Jim Cakalic
---------- ApplicationFrame.java ----------
import java.awt.*;
import java.awt.event.*;
public class ApplicationFrame extends Frame {
public ApplicationFrame() {
this("ApplicationFrame v1.0");
}
public ApplicationFrame(String title) {
super(title);
createUI();
}
protected void createUI() {
setSize(500, 400);
center();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
public void center() {
Dimension screenSize = Toolkit.getDefaultToolkit(
Dimension frameSize = getSize();
int x = (screenSize.width - frameSize.width) / 2;
int y = (screenSize.height - frameSize.height) / 2;
setLocation(x, y);
}
}
---------- SmoothMove.java ----------
import java.awt.*;
import java.awt.event.*;
public class SmoothMove extends ApplicationFrame implements MouseMotionListener {
public static void main(String[] args) {
new SmoothMove();
}
private int mX, mY;
private Image mImage;
public SmoothMove() {
super("SmoothMove v1.0");
addMouseMotionListener(thi
setVisible(true);
}
public void mouseMoved(MouseEvent me) {
mX = (int)me.getPoint().getX();
mY = (int)me.getPoint().getY();
repaint();
}
public void mouseDragged(MouseEvent me) {
mouseMoved(me);
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
// Clear the offscreen image.
Dimension d = getSize();
checkOffscreenImage();
Graphics offG = mImage.getGraphics();
offG.setColor(getBackgroun
offG.fillRect(0, 0, d.width, d.height);
// Draw into the offscreen image.
paintOffscreen(mImage.getG
// Put the offscreen image on the screen.
g.drawImage(mImage, 0, 0, null);
}
private void checkOffscreenImage() {
Dimension d = getSize();
if (mImage == null ||
mImage.getWidth(null) != d.width ||
mImage.getHeight(null) != d.height) {
mImage = createImage(d.width, d.height);
}
}
public void paintOffscreen(Graphics g) {
int s = 100;
g.setColor(Color.blue);
g.fillRect(mX - s / 2, mY - s / 2, s, s);
}
}
I hope this helps.
Jim Cakalic
ASKER
Adjusted points from 25 to 50
ASKER
Jim, thanks for you input.
I am not using an image in my code, I am drawing shapes using swing. Also, I start a thread which calculates the positions of the shape and calls the repaint() method (which in turns call paintComponent). The structure of my code is somewhat like this:
class myOutermostClass {
tAnimateButton.addMouseLis tener(
new MouseAdapter {
public void mouseClicked () {
Animate doAnimate = new Animate;
doAnimate.start();
}
}
);
class DrawPanel Extends JPanel implements ...{
.....
public void paintComponent (Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
....
call method to draw shape
}
class Animate extends Thread () {
public void run() {
while loop for number of frames {
while loop for no. of shapes in vector {
calculate position & size of shape
}
tDrawPanel.repaint();
}
}
}
}
To my uderstanding the tDrawPanel.repaint statement calls the paintComponent of DrawPanel, so it should execute the setColor(Color.white) in the paintComponent method. It coud be that I have made the call to repaint in wrong place.
Above should give more info to experts.
Thanks for your help.
Theta.
I am not using an image in my code, I am drawing shapes using swing. Also, I start a thread which calculates the positions of the shape and calls the repaint() method (which in turns call paintComponent). The structure of my code is somewhat like this:
class myOutermostClass {
tAnimateButton.addMouseLis
new MouseAdapter {
public void mouseClicked () {
Animate doAnimate = new Animate;
doAnimate.start();
}
}
);
class DrawPanel Extends JPanel implements ...{
.....
public void paintComponent (Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
....
call method to draw shape
}
class Animate extends Thread () {
public void run() {
while loop for number of frames {
while loop for no. of shapes in vector {
calculate position & size of shape
}
tDrawPanel.repaint();
}
}
}
}
To my uderstanding the tDrawPanel.repaint statement calls the paintComponent of DrawPanel, so it should execute the setColor(Color.white) in the paintComponent method. It coud be that I have made the call to repaint in wrong place.
Above should give more info to experts.
Thanks for your help.
Theta.
Ok, by using paintComponent (or paint) you are painting over the entire panel. I think this was the first option I mentioned. I would suggest using the paint method instead because it circumvents the UImanager.
public void paint(Graphics g){
g.setColor(Color.white);
g.fillRect(0, 0, maxX, maxY);
g.setColor(Color.green);
g.fillOval(xPos, yPos, 10, 10);
}
This will paint an oval at(xPos, yPos). If you change the position, then the circle will be redrawn at the new location ,and the old one will be erased.
public void paint(Graphics g){
g.setColor(Color.white);
g.fillRect(0, 0, maxX, maxY);
g.setColor(Color.green);
g.fillOval(xPos, yPos, 10, 10);
}
This will paint an oval at(xPos, yPos). If you change the position, then the circle will be redrawn at the new location ,and the old one will be erased.
The following self-contained sample code is a simplified version of what I think you are trying to do. This behaves as expected under jdk1.3rc1 but I'm not sure about previous jdks. I'll try to test it under jdk1.2 versions. Check this against your actual code to see where the differences lie.
Jim Cakalic
---------- SwingPaintDemo.java ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingPaintDemo {
public static void main(String[] args) {
JFrame f = new JFrame("Brownian Motion");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
ShapePanel panel = new ShapePanel();
new Animate(panel).start();
f.getContentPane().add(pan el, BorderLayout.CENTER);
f.setSize(500, 500);
f.show();
}
}
class Animate extends Thread {
ShapePanel panel;
public Animate(ShapePanel panel) {
this.panel = panel;
}
public void run() {
while (true) {
int x = (int)(Math.random() * panel.getWidth());
int y = (int)(Math.random() * panel.getHeight());
panel.setOrigin(x, y);
}
}
}
class ShapePanel extends JPanel {
private int x, y;
public ShapePanel() {
super();
setLayout(new BorderLayout());
setBorder(BorderFactory.cr eateLineBo rder(Color .black));
}
public void setOrigin(int x, int y) {
this.x = x;
this.y = y;
repaint();
}
protected void paintComponent(Graphics g) {
Dimension size = getSize();
g.setColor(Color.white);
g.fillRect(0, 0, size.width, size.height);
g.setColor(Color.red);
g.fillOval(x, y, 50, 50);
}
}
Jim Cakalic
---------- SwingPaintDemo.java ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingPaintDemo {
public static void main(String[] args) {
JFrame f = new JFrame("Brownian Motion");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
ShapePanel panel = new ShapePanel();
new Animate(panel).start();
f.getContentPane().add(pan
f.setSize(500, 500);
f.show();
}
}
class Animate extends Thread {
ShapePanel panel;
public Animate(ShapePanel panel) {
this.panel = panel;
}
public void run() {
while (true) {
int x = (int)(Math.random() * panel.getWidth());
int y = (int)(Math.random() * panel.getHeight());
panel.setOrigin(x, y);
}
}
}
class ShapePanel extends JPanel {
private int x, y;
public ShapePanel() {
super();
setLayout(new BorderLayout());
setBorder(BorderFactory.cr
}
public void setOrigin(int x, int y) {
this.x = x;
this.y = y;
repaint();
}
protected void paintComponent(Graphics g) {
Dimension size = getSize();
g.setColor(Color.white);
g.fillRect(0, 0, size.width, size.height);
g.setColor(Color.red);
g.fillOval(x, y, 50, 50);
}
}
ASKER
If I can add something to the paintComponent method, what method should I use to paint the panel, since setColor and fillRect are not doing what I am looking for.
Theta