Flickering When Redrawing in a Canvas (Again!)
Hi,
I realise this question has been asked a million times, however I'm having trouble getting a Canvas to draw without flickering.
I've tried to implement offscreen drawing however this doesn't seem to be working.
What am I doing wrong here?
import java.awt.*;
import java.util.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.image.*;
publicclass myCanvasextends Canvas
{
publicint W;
publicint H;
public Vector Obstacles;
public Label messageLabel;
public visibility visibilitygraf;
public Path ShortestPath;
Point StartPoint;
Point EndPoint;
Vector invRobot;
publicboolean paintVisGraph;
publicboolean paintShortestPath;
private Dimension offDimension;
private Image offImage;
private Graphics2D offGraphics;
//============================================================
public myCanvas(){
setBackground(Color.white);
paintVisGraph =false;
paintShortestPath =false;
offDimension =new Dimension();
}
//============================================================
publicvoid setPaintVisGraph(){
paintVisGraph = !paintVisGraph;
repaint();
}
//============================================================
publicvoid setPaintShortestPath(){
paintShortestPath = !paintShortestPath;
repaint();
}
//============================================================
publicvoid paint(Graphics g){
repaint(g);
}
//============================================================
publicvoid repaint(Graphics g)
{
Dimension d = getSize();
if((offGraphics ==null) || (d.width != offDimension.width) || (d.height != offDimension.height) ){
offDimension = d;
offImage = createImage(d.width, d.height);
offGraphics = (Graphics2D)offImage.getGraphics();
}
// Erase the offscreen buffer.
offGraphics.setColor(getBackground());
offGraphics.fillRect(0, 0, d.width, d.height);
offGraphics.setColor(Color.black);
//Graphics2D graphics2d = (Graphics2D)g;
//============================================================
// The objects.
if(Obstacles !=null){
for(int j = 0; j < Obstacles.size(); j++){
Polygon polygon1 =new Polygon();
Obstacle obstacle1 = (Obstacle)Obstacles.elementAt(j);
for(int l = 0; l < obstacle1.ObstaclePoints.size(); l++){
Point point1 = (Point)obstacle1.ObstaclePoints.elementAt(l);
polygon1.addPoint(point1.x, point1.y);
}
offGraphics.fillPolygon(polygon1);
}
}
//============================================================
// The source and the destination
offGraphics.setColor(Color.red);
if(StartPoint !=null){
offGraphics.fillOval(StartPoint.x - 5, StartPoint.y - 5, 10, 10);
}
offGraphics.setColor(Color.green);
if(EndPoint !=null){
offGraphics.fillOval(EndPoint.x - 5, EndPoint.y - 5, 10, 10);
}
//============================================================
// The graph.
if(paintVisGraph ==true){
if(visibilitygraf !=null){
offGraphics.setColor(Color.blue);
offGraphics.setStroke(new BasicStroke(1.0F));
for(int k1 = 0; k1 < visibilitygraf.visibilityedges.size(); k1++){
offGraphics.drawLine(((edge)visibilitygraf.visibilityedges.elementAt(k1)).p1.x, ((edge)visibilitygraf.visibilityedges.elementAt(k1)).p1.y, ((edge)visibilitygraf.visibilityedges.elementAt(k1)).p2.x, ((edge)visibilitygraf.visibilityedges.elementAt(k1)).p2.y);
}
}
}
//============================================================
// The shortest path.
offGraphics.setStroke(new BasicStroke(2.0F));
if(paintShortestPath ==true){
if(ShortestPath !=null){
offGraphics.setColor(Color.red);
for(int l1 = 0; l1 < ShortestPath.points.size() - 1; l1++){
Point point4 = (Point)ShortestPath.points.elementAt(l1);
Point point5 = (Point)ShortestPath.points.elementAt(l1 + 1);
offGraphics.drawLine(point4.x, point4.y, point5.x, point5.y);
}
}
}
//============================================================
// Paint the image onto the screen.
g.drawImage(offImage, 0, 0,this);
}
}
[8026 byte] By [
cpsmusica] at [2007-11-27 10:46:14]

# 1
Check out how to do this in my PaintArea class
/*
* Created on Jun 15, 2005 by @author Tom Jacobs
*
*/
package tjacobs.ui;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import tjacobs.MathUtils;
/**
* PaintArea is a component that you can draw in similar to but
* much simpler than the windows paint program.
*/
public class PaintArea extends JComponent {
BufferedImage mImg; //= new BufferedImage();
int mBrushSize = 1;
private boolean mSizeChanged = false;
private Color mColor1, mColor2;
static class PaintIcon extends ImageIcon {
int mSize;
public PaintIcon(Image im, int size) {
super(im);
mSize = size;
}
}
public PaintArea() {
super();
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
addComponentListener(new CListener());
MListener ml = new MListener();
addMouseListener(ml);
addMouseMotionListener(ml);
setBackground(Color.WHITE);
setForeground(Color.BLACK);
}
public void paintComponent(Graphics g) {
if (mSizeChanged) {
handleResize();
}
//g.drawImage(mImg, mImg.getWidth(), mImg.getHeight(), null);
g.drawImage(mImg, 0, 0, null);
//super.paintComponent(g);
//System.out.println("Image = " + mImg);
//System.out.println("Size: " + mImg.getWidth() + "," + mImg.getHeight());
}
public void setBackground(Color c) {
super.setBackground(c);
if (mImg != null) {
Graphics g = mImg.getGraphics();
g.setColor(c);
g.fillRect(0, 0, mImg.getWidth(), mImg.getHeight());
g.dispose();
}
}
public void setColor1(Color c) {
mColor1 = c;
}
public void setColor2(Color c) {
mColor2 = c;
}
public Color getColor1() {
return mColor1;
}
public Color getColor2() {
return mColor2;
}
class ToolBar extends JToolBar {
ToolBar() {
final ColorButton fore = new ColorButton();
fore.setToolTipText("Foreground Color");
final ColorButton back = new ColorButton();
back.setToolTipText("Background Color");
JComboBox brushSize = new JComboBox();
//super.createImage(1, 1).;
FontMetrics fm = new FontMetrics(getFont()) {};
int ht = fm.getHeight();
int useheight = fm.getHeight() % 2 == 0 ? fm.getHeight() + 1 : fm.getHeight();
final BufferedImage im1 = new BufferedImage(useheight, useheight, BufferedImage.TYPE_INT_RGB);
Graphics g = im1.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, useheight, useheight);
g.setColor(Color.BLACK);
g.fillOval(useheight / 2, useheight / 2, 1, 1);
g.dispose();
//im1.setRGB(useheight / 2 + 1, useheight / 2 + 1, 0xFFFFFF);
final BufferedImage im2 = new BufferedImage(useheight, useheight, BufferedImage.TYPE_INT_RGB);
g = im2.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, useheight, useheight);
g.setColor(Color.BLACK);
g.fillOval(useheight / 2 - 1, useheight / 2 - 1, 3, 3);
g.dispose();
//im2.setRGB(useheight / 2 - 1, useheight / 2 - 1, 3, 3, new int[] {0, 0xFFFFFF, 0,
//0xFFFFFF, 0xFFFFFFF, 0xFFFFFF,
//0, 0xFFFFFF, 0}, 0, 1);
final BufferedImage im3 = new BufferedImage(useheight, useheight, BufferedImage.TYPE_INT_RGB);
g = im3.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, useheight, useheight);
g.setColor(Color.BLACK);
g.fillOval(useheight / 2 - 2, useheight / 2 - 2, 5, 5);
g.dispose();
//im3.setRGB(useheight / 2 - 2, useheight / 2 - 2, 5, 5, new int[] {0, 0, 0xFFFFFF, 0, 0,
//0, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFF, 0,
//0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF,
//0, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFF, 0,
//0, 0, 0xFFFFFF, 0, 0}, 0, 1);
//JLabel l1 = new JLabel("1 pt", new ImageIcon(im1), JLabel.LEFT);
//JLabel l2 = new JLabel("3 pt", new ImageIcon(im2), JLabel.LEFT);
//JLabel l3 = new JLabel("5 pt", new ImageIcon(im3), JLabel.LEFT);
brushSize.addItem(new PaintIcon(im1, 1));
brushSize.addItem(new PaintIcon(im2, 3));
brushSize.addItem(new PaintIcon(im3, 5));
//brushSize.addItem("Other");
add(fore);
add(back);
add(brushSize);
PropertyChangeListener pl = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
Object src = ev.getSource();
if (src != fore && src != back) {
return;
}
Color c = (Color) ev.getNewValue();
if (ev.getSource() == fore) {
mColor1 = c;
}
else {
mColor2 = c;
}
}
};
fore.addPropertyChangeListener("Color", pl);
back.addPropertyChangeListener("Color", pl);
fore.changeColor(Color.BLACK);
back.changeColor(Color.WHITE);
brushSize.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
System.out.println("ItemEvent");
if (ev.getID() == ItemEvent.DESELECTED) {
return;
}
System.out.println("Selected");
Object o = ev.getItem();
mBrushSize = ((PaintIcon) o).mSize;
}
});
//Graphics g = im1.getGraphics();
//g.fillOval(0, 0, 1, 1);
//BufferedImage im1 = new BufferedImage();
//BufferedImage im1 = new BufferedImage();
}
}
protected class MListener extends MouseAdapter implements MouseMotionListener {
Point mLastPoint;
public void mouseDragged(MouseEvent me) {
Graphics g = mImg.getGraphics();
if ((me.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
g.setColor(mColor1);
} else {
g.setColor(mColor2);
}
Point p = me.getPoint();
if (mLastPoint == null) {
g.fillOval(p.x - mBrushSize / 2, p.y - mBrushSize / 2, mBrushSize, mBrushSize);
//g.drawLine(p.x, p.y, p.x, p.y);
}
else {
g.drawLine(mLastPoint.x, mLastPoint.y, p.x, p.y);
//g.fillOval(p.x - mBrushSize / 2, p.y - mBrushSize / 2, mBrushSize, mBrushSize);
double angle = MathUtils.angle(mLastPoint, p);
if (angle < 0) {
angle += 2 * Math.PI;
}
double distance = MathUtils.distance(mLastPoint, p) * 1.5;
if (angle < Math.PI / 4 || angle > 7 * Math.PI / 4 || Math.abs(Math.PI - angle) < Math.PI / 4) {
for (int i = 0; i < mBrushSize / 2; i ++) {
g.drawLine(mLastPoint.x, mLastPoint.y + i, p.x, p.y + i);
g.drawLine(mLastPoint.x, mLastPoint.y - i, p.x, p.y - i);
//System.out.println("y");
//System.out.println("angle = " + angle / Math.PI * 180);
}
}
else {
for (int i = 0; i < mBrushSize / 2; i ++) {
g.drawLine(mLastPoint.x + i, mLastPoint.y, p.x + i, p.y);
g.drawLine(mLastPoint.x - i, mLastPoint.y, p.x - i, p.y);
//System.out.println("x");
}
}
//System.out.println("new = " + PaintUtils.printPoint(p));
//System.out.println("last = " + PaintUtils.printPoint(mLastPoint));
//System.out.println("distance = " + distance);
//Graphics2D g2 = (Graphics2D) g;
//g2.translate(mLastPoint.x + mBrushSize / 2, mLastPoint.y);
//g2.rotate(angle);
//g2.fillRect(0, 0, (int) Math.ceil(distance), mBrushSize);
//g2.rotate(-angle);
//g2.translate(-mLastPoint.x + mBrushSize / 2, -mLastPoint.y);
//g.setColor(Color.RED);
//g.drawRect(p.x, p.y, 1, 1);
}
mLastPoint = p;
g.dispose();
repaint();
}
public void mouseMoved(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {
mLastPoint = null;
}
}
private void handleResize() {
Dimension size = getSize();
mSizeChanged = false;
if (mImg == null) {
mImg = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
Graphics g = mImg.getGraphics();
g.setColor(getBackground());
g.fillRect(0, 0, mImg.getWidth(), mImg.getHeight());
g.dispose();
}
else {
int newWidth = Math.max(mImg.getWidth(),getWidth());
int newHeight = Math.max(mImg.getHeight(),getHeight());
if (newHeight == mImg.getHeight() && newWidth == mImg.getWidth()) {
return;
}
BufferedImage bi2 = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = bi2.getGraphics();
g.setColor(getBackground());
g.fillRect(0, 0, bi2.getWidth(), bi2.getHeight());
g.drawImage(mImg, mImg.getWidth(), mImg.getHeight(), null);
g.dispose();
mImg = bi2;
}
}
public JToolBar getToolBar() {
if (mToolBar == null) {
mToolBar = new ToolBar();
}
return mToolBar;
}
private ToolBar mToolBar;
public static void main (String args[]) {
PaintArea pa = new PaintArea();
JPanel parent = new JPanel();
parent.setLayout(new BorderLayout());
parent.add(pa, BorderLayout.CENTER);
pa.setPreferredSize(new Dimension(150, 150));
parent.add(pa.getToolBar(), BorderLayout.NORTH);
WindowUtilities.visualize(parent);
}
protected class CListener extends ComponentAdapter {
public void componentResized(ComponentEvent ce) {
mSizeChanged = true;
}
}
}