Click to See Complete Forum and Search --> : Graphics / Image-Handling problem


javaQQ
June 11th, 2006, 04:43 PM
I am trying to draw an image of one JPanel onto another JPanel, using the code below.
Instead of a picture of the source JPanel, i get only a white rectangle on the target JPanel.
I would greatly appreciate any help on fixing my code.

A JPanel, "sourcePanel" exists.
...


GraphicsConfiguration gfxConfig =
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
BufferedImage sourcePanelImage =
gfxConfig.createCompatibleImage(sourcePanel.getWidth(),
sourcePanel.getHeight());
Graphics2D sourceGraphics =
(Graphics2D) sourcePanelImage.getGraphics();
sourcePanel.paint (sourceGraphics);

TargetPanel targetPanel = new TargetPanel( sourcePanelImage.getWidth(), sourcePanelImage.getHeight(), sourcePanelImage );
PopFrame popFrame2 = new PopFrame( targetPanel, sourcePanelImage.getWidth(), sourcePanelImage.getHeight() );
...

import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;

class TargetPanel extends JPanel {
int width;
int height;
BufferedImage image;


public TargetPanel( int width, int height, BufferedImage image ) {
this.width = width;
this.height = height;
this.image = image;

setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
setPreferredSize( new Dimension( width, height ) );
setMinimumSize( new Dimension( width, height ) );
setMaximumSize( new Dimension( width, height ) );
setBackground( Color.orange );

}

public void paintComponent(Graphics g) {
super.paintComponent(g); // Paint background, borders
g.drawImage( image, 0, 0, width, height, this );
}
}
...


Println's show that the image exists:
"sourcePanelImage.getWidth() = 170
sourcePanelImage.getHeight() = 180
sourcePanelImage = BufferedImage@b4ee5e: type = 3 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 IntegerInterleavedRaster: width = 170 height = 180 #Bands = 4 xOff = 0 yOff = 0 dataOffset[0] 0
"

but the result is only a white rectangle on "targetPanel"

Many thanks in advance for a solution.

keang
June 12th, 2006, 03:02 PM
I've knocked up a simple repetative draw and capture test app based on the code given and it seems to work about 30% of the time. :confused:

However if you change

sourcePanel.paint (sourceGraphics);to

sourcePanel.printAll (sourceGraphics);
it seems to work all of the time :)

Unfortunately I can't give you an explanation as to why but I suspect it a synchronisation issue.

dlorde
June 12th, 2006, 06:41 PM
I think the problem may be that a panel doesn't have an accessible size or image until it is displayed, i.e. until it is visible. This means you need to wait until the source panel has been displayed before extracting an image from it for the target panel. One way to do this is to put a window listener on the frame that will display the source panel and create your graphics image in the windowOpened(...) method - then you can create the new TestPanel with the image and display it... it works for me :)

The person who says it cannot be done should not interrupt the person doing it...
Chinese proverb.

keang
June 13th, 2006, 07:43 AM
Hi dlorde,

I think the problem may be that a panel doesn't have an accessible size or image until it is displayed That was my first thought as well but if the panel wasn't displayed the call to sourcePanel.getWidth() would return 0 - it's returning the correct (display) panel size. And anyway as the paint() method is being called with the graphics object of our own BufferedImage it will work regardless of its current display state. Afterall the paint() method doesn't know (or care) if its object is displayed or not it just draws using the graphics object it is given.

My test program moved an image slowly across a panel and every 10th move did a 'capture' and displayed the result in a second panel. So one panel had an image that moved smoothly the other had an identical image that hopped across.
When run, it successfully captures the image on the first couple of increments and then randomly fails to fully capture the image, sometimes drawing no image, sometimes drawing a partial image and sometimes the full image and very occasionally it locks up. Interestingly I'm getting a much higher sucess rate day than yesterday, it now works about 95% of the time.

Changing the call from paint() to printAll() solves all the problems. Any ideas as to why the problem occurs (it sounds like a thread sync problem to me) and why changing to printAll solves it?

dlorde
June 13th, 2006, 08:39 AM
Any ideas as to why the problem occurs (it sounds like a thread sync problem to me) and why changing to printAll solves it?No, not really. It does sound like a threading problem, and it may be related to double-buffering. If I find more time & energy (it's hot here atm), I may investigate further... (but I doubt it).

Imagination is more important than knowledge...
A. Einstein.

keang
June 13th, 2006, 08:59 AM
it may be related to double-buffering.Of course, printAll() is basically a paint without doubleBuffering.
I've re-run the test using paint() and with doubleBuffering disabled on the source panel and it appears to work 100% of the time. Cheers.