R
Roger Davis
I am trying to draw a complicated image into an on-screen window
and make frequent, minor changes to that image, usually in
response to user input, e.g., draw a rubberband bounding box, etc.
I want to make these changes without having to completely
redraw the image , i.e., I want to redraw only the small part
of the image which has changed. Unfortunately every approach
I have tried results in failure -- when I try to redraw some
small part of my image, the unchanged (and un-redrawn) portion
of the image disappears from the display. I have been
stumbling lost through repaint() hell for three days now with
no end in sight, and am hoping that someone out there can
tell me how to do this. I am using Java 2 SE 1.4.2.
I am an X11 programmer who is new to Java, so I may be going
about this completely wrong, but here is what I am doing (based
largely on suggestions from various Java books). My drawing
object, called a Drawable, is an instantiation of my own direct
subclass of JComponent. This Drawable object is encapsulated in a
JScrollPane which has been stuffed into the content pane of a JFrame,
which also has a JMenuBar. I am doing my drawing into an off-screen
BufferedImage which I have allocated myself. Every time I perform
a drawing operation on this BufferedImage, e.g., adjusting a rubberband
bounding box, I create a Rectangle which bounds the affected area and
place it onto a queue, and call the JComponent.repaint() method. I
have overridden the JComponent.paint() method in my Drawable
class to examine this queue and transfer the appropriate subsections
of the BufferedImage into the Drawable. When my program starts
and creates the initial large, complicated image and transfers the
whole thing into the Drawable this works fine. What does *not*
work is when I subsequently redraw some small piece of the image
and then call repaint(), which forces a call to paint() -- when this
happens the entire contents of the on-screen Drawable are wiped out,
and all I see is my small updated area. Some agent external to my
Drawable's paint() method is clearing the Drawable before that
paint() method is called.
I tried overriding JComponent's update() method as suggested in
various books, but then found out that Swing does not even call
JComponent.update(), which I confirmed empirically by putting print
statements in my own overriding Drawable.update() method.
I then discovered documentation in various places which mention some
sneaky ComponentUI.update() method which may be clearing my JComponent.
However, Sun's Javadoc says that this should happen only if the
JComponent is opaque, and mine is not (at least according to isOpaque()
at the time of creation of the JComponent -- I have not explicitly set
it either way). Also, I've found other documentation that implies
that this does not happen anyway if you are working with your own
direct subclass of JComponent and have not explicitly created your
own UI delegate. (I *am* using my own direct subclass of JComponent and
I have *not* explicitly created any UI delegate. I don't even have a
clue of what a UI delegate is.)
After all of the above failed to get me anywhere, I scrapped the whole
BufferedImage approach and tried to use Swing's own double-buffering.
I have no idea if this is even possible and was not able to find any
programming examples, so I may have gone about it completely wrong,
but the bottom line is that failed also. I did a setDoubleBuffered()
on my JComponent and did all of my draws to the JComponent, then called
repaint(rect) after each drawing operation, where rect is the smallest
bounding Rectangle that contained the affected area. I did not override
JComponent.paint() in this attempt. This basically did the
same thing as my BufferedImage approach, only with a lot more flicker.
There has *got* to be a way to do this. I hope someone out there can
tell me how!
Thanks.
and make frequent, minor changes to that image, usually in
response to user input, e.g., draw a rubberband bounding box, etc.
I want to make these changes without having to completely
redraw the image , i.e., I want to redraw only the small part
of the image which has changed. Unfortunately every approach
I have tried results in failure -- when I try to redraw some
small part of my image, the unchanged (and un-redrawn) portion
of the image disappears from the display. I have been
stumbling lost through repaint() hell for three days now with
no end in sight, and am hoping that someone out there can
tell me how to do this. I am using Java 2 SE 1.4.2.
I am an X11 programmer who is new to Java, so I may be going
about this completely wrong, but here is what I am doing (based
largely on suggestions from various Java books). My drawing
object, called a Drawable, is an instantiation of my own direct
subclass of JComponent. This Drawable object is encapsulated in a
JScrollPane which has been stuffed into the content pane of a JFrame,
which also has a JMenuBar. I am doing my drawing into an off-screen
BufferedImage which I have allocated myself. Every time I perform
a drawing operation on this BufferedImage, e.g., adjusting a rubberband
bounding box, I create a Rectangle which bounds the affected area and
place it onto a queue, and call the JComponent.repaint() method. I
have overridden the JComponent.paint() method in my Drawable
class to examine this queue and transfer the appropriate subsections
of the BufferedImage into the Drawable. When my program starts
and creates the initial large, complicated image and transfers the
whole thing into the Drawable this works fine. What does *not*
work is when I subsequently redraw some small piece of the image
and then call repaint(), which forces a call to paint() -- when this
happens the entire contents of the on-screen Drawable are wiped out,
and all I see is my small updated area. Some agent external to my
Drawable's paint() method is clearing the Drawable before that
paint() method is called.
I tried overriding JComponent's update() method as suggested in
various books, but then found out that Swing does not even call
JComponent.update(), which I confirmed empirically by putting print
statements in my own overriding Drawable.update() method.
I then discovered documentation in various places which mention some
sneaky ComponentUI.update() method which may be clearing my JComponent.
However, Sun's Javadoc says that this should happen only if the
JComponent is opaque, and mine is not (at least according to isOpaque()
at the time of creation of the JComponent -- I have not explicitly set
it either way). Also, I've found other documentation that implies
that this does not happen anyway if you are working with your own
direct subclass of JComponent and have not explicitly created your
own UI delegate. (I *am* using my own direct subclass of JComponent and
I have *not* explicitly created any UI delegate. I don't even have a
clue of what a UI delegate is.)
After all of the above failed to get me anywhere, I scrapped the whole
BufferedImage approach and tried to use Swing's own double-buffering.
I have no idea if this is even possible and was not able to find any
programming examples, so I may have gone about it completely wrong,
but the bottom line is that failed also. I did a setDoubleBuffered()
on my JComponent and did all of my draws to the JComponent, then called
repaint(rect) after each drawing operation, where rect is the smallest
bounding Rectangle that contained the affected area. I did not override
JComponent.paint() in this attempt. This basically did the
same thing as my BufferedImage approach, only with a lot more flicker.
There has *got* to be a way to do this. I hope someone out there can
tell me how!
Thanks.