File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
The moose likes Swing / AWT / SWT and the fly likes Canvas HELP!!! Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "Canvas HELP!!!" Watch "Canvas HELP!!!" New topic

Canvas HELP!!!

colin shuker
Ranch Hand

Joined: Apr 11, 2005
Posts: 750
Hi, I'm trying to draw things into a frame, that already has something drawn onto it. The code I have below draws squares on top of a jpg picture,
in a sequence. The squares are drawn using the Box class, which ive extended from the Canvas class.
This works, but there are a trail of squares being left on the frame.
This isn't what a want. I want to for example, be able to move the squares, or stretch them, WITHOUT redrawing the jpg picture( or whatever drawing is underneath).
I would be grateful if someone could modify my code so that instead of a sequence of squares being drawn, you actual see the square moving across the screen.
I was told I needed to use Canvas to do this, but I dont know how.
To explain the reasoning why I want to do this, I have a program that draws fractals onto a frame(Mandelbrot set to be precise), how ever it takes quite a while to draw one to a frame, and I would like to be able to use an adjustable box in the frame, so that I can zoom in to the box area.
So, if I can figure how to display and remove something, or display something and move it, then I'm sure I can construct an adjustable box.

Hope thats not too confusing.
Here is my code for the squares program that I'm trying to fix.

Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
Some comments and suggestions:
1 — Swing makes animated drawing pretty easy. I recommend you begin by drawing the image and drawing your graphic over it as shown below. This will often work just fine. If you must keep the drawing separate from the image rendering then I would suggest a non–opaque JPanel on top of the image component set in an OverlayLayout.

You can use a glass pane as shown in the tutorial but this covers the JRootPane which, if it includes other components may require
a – additional work to transfer InputEvents through to the components, and
b – translation of coordinates between glass pane and image component.

There is a third technique of doing all the rendering in a BufferedImage and simply painting the image in the 'paintComponent' method after each update in the animation. This works well for building up images/graphics over time.

2 – Using ImageIcon.getImage is an older method (j2se 1.2) for loading images. The single line of code does not give any feedback for loading problems although it is easy enough to add (ImageIcon and MediaTracker api). The newer way (j2se 1.4) is to use ImageIO whose 'read' methods return a BufferedImage. Using BufferedImages allow for software acceleration; your code can run faster.

Loading an image every time you render graphics (in 'paintComponent') is inefficient. You only need to load the image one time.

3 — it is common practice to use a javax.swing.Timer or a thread for delays/animation. The example below shows one way of doing this.

4 — Canvas is an AWT component. You can mix AWT/heavyweight and Swing/lightweight components but it takes some care to get good results. It is generally recommended that we do not mix them. In Swing we generally use either JComponent or JPanel for custom drawing. JComponent is non–opaque by default and JPanel is opaque.

Here is a basic animation setup.

As far as zooming in and out of a portion of the graphics (image/drawings) you can use a Rectangle that can be resizable/draggable and expand the portion of the graphics it clips/contains to fill the graphic component. Or you can leave the Rectangle alone and scale the graphics it clips up or down. AffineTransform tries to make this easy with methods for scaling and translating. Also, the BufferedImage class has a handy 'subimage' method.
colin shuker
Ranch Hand

Joined: Apr 11, 2005
Posts: 750
Hi, I've just executed your program, its very nice and does the kind of thing I'm after. I'm going to try and figure out how it works now.
I see you've got threads in there, unfortunately I have a phobia of threads, but I'll see what I can do.
Regarding the fractal program I mentioned. It is almost complete, you can draw out a box using the mouse, and this region is then zoomed in on, but no box is actually drawn when your moving the mouse, you have to use your imagination, which is the reason behind my posts.
Thanks again for your code, I'll let you know if I get stuck.

colin shuker
Ranch Hand

Joined: Apr 11, 2005
Posts: 750
OK, I've just looked through it, and there is a problem.
In the paintComponent() method of Drawing, you are dislaying the image, and then drawing the square.
This is no good for me, as I said above. If it's going to take 20 seconds to draw the fractal on screen, it will be impossible to draw the square on top of this picture and move it about, since each slight movement of the square will mean the whole fractal will have to be drawn again, which means millions more calculations, which is what I'm trying to avoid.
I was just using a jpg image earlier as an example of something in the background, but in the fractal program, the JFrame will actually be showing the result of millions of calculations, hence the slowness.
I was recommended to use a Canvas to get around this, but I don't know how.
Hope you can help. Thanks
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
Here's an example of the OverlayLayout technique.

In either case you could draw the fractal into a BufferedImage and draw the image as often as you like.

This will help avoid re–creating the fractal for system–triggered repaints which are caused by things like restoring the component after minimizing or partial covering by other apps.
colin shuker
Ranch Hand

Joined: Apr 11, 2005
Posts: 750
Thanks very much Craig, I've used the OverlayLayout technique first, which
worked. But then I realised that if I want to go backwards and forwards through the fractal images, I would need to save them. I've just done a quick test using the BufferedImage technique and amazingly it works.
I'm not sure about BufferedImage.TYPE_ thing, but I'll try out different TYPES when i've got it up and running correctly.
It's a lot easier this way as well. It's a bit confusing at the moment, eg yur getPanel() method, I have never done it before like that.
Usually I would just do
But I'll figure it out eventually
Thanks again.
I'm sure I'll get stuck soon with something, so your help is kindly
I agree. Here's the link:
subject: Canvas HELP!!!
It's not a secret anymore!