I am experimenting with Java
and GUI manipulation and I have a custom dialog created from a jPanel
imaginatively called DLog, which appears on request to collect user input. This works fine, but of course my dialog is not modal, which leaves the rest of the controls visible and accessible to the user while the dialog is open. Not good at all!
To overcome this I have a separate jPanel
called DLogCover which sizes with the window but which is invisible until required. When the custom dialog is shown a screenshot of my window is taken and shown as an image in a label on the DLogCover, which appears beneath my custom dialog, but above everything else (On the MODAL_LAYER
of a jLayeredPanel
- the custom dialog appears on the POPUP_LAYER
). This works exactly as planned although there are two niggling points which I hope you may be able to help with.
Firstly the screenshot of course includes the title bar and left border of the window. I have taken this into account using arbitrary numbers which work for me right now, but of course this will be different on every OS because I use the system Look and feel and these sizes might be incorrect.
Question: Is there any way to make sure that my screenshot is only of the inner content of my window (or any way to always get the correct sizes for the title bar and borders of the window, regardless of OS)?
Secondly, while my screenshot works fine it is simply an image of the window, and I would like to have it slightly faded or blurred in order to make it appear that there is in fact something covering the controls.
Question: Is there any way to manipulate an image to give this appearance?
Here is the code I am using to capture the image and display it (before showing the custom dialog):
DLOGCover.setVisible(true);
Point pos = this.getLocationOnScreen();
Dimension dim = this.getSize();
//Arbitrary sizes! These need to be discovered and set correctly!
int xLoc = pos.x +1 ;
int yLoc = pos.y + 11;
try
{
Robot robot = new Robot();
Rectangle captureSize = new Rectangle(xLoc, yLoc, dim.width, dim.height);
BufferedImage bImage = robot.createScreenCapture(captureSize);
Image imgwork = (Image)bImage;
ImageIcon labelimg = new ImageIcon(imgwork);
imageLabel.setIcon(labelimg);
}
catch(AWTException e)
{
System.err.println("Ouch!");
}
//... show the custom dialog
Many thanks for any help you can give, and as before, the reason I am doing things this way is because I am trying to learn Java
so I am experimenting, and currently it is with this!
Many thanks for any help you can give, and of course I am open to suggestions about alternative methods for achieving the same thing.
Some Answers
Id like to add this information so that any others who come looking can find the it.
Thanks to Andrew Thompson's code (many thanks to nIcE cOw for the link) I can now get a screenshot of just my window contents, negating the need to try and work out titlebar and border sizes:
public static BufferedImage getScreenShot(Component component)
{
BufferedImage image = new BufferedImage(
component.getWidth(),
component.getHeight(),
BufferedImage.TYPE_INT_RGB
);
// call the Component's paint method, using
// the Graphics object of the image.
component.paint( image.getGraphics() );
return image;
}
This is called when I open my custom dialog and I am then able to modify the image to darken and blur it a little then display it in a jLabel
which exists on my custom DLogCover (which is just a jPanel
and a jLabel
for the image):
//get the screenshot
BufferedImage bufferedImage = getScreenShot( this.getContentPane() );
//blur and darken the image slightly
Kernel myKernel = new Kernel(3, 3,new float[] {1f/9f, 1f/9f, 1f/9f,1f/9f, 1f/9f, 1f/9f,1f/9f, 1f/9f, 1f/9f});
BufferedImageOp myOp1 = new ConvolveOp(myKernel);
bufferedImage = myOp1.filter(bufferedImage, null);
RescaleOp myOp2 = new RescaleOp(.6f, 0, null);
bufferedImage = myOp2.filter(bufferedImage, null);
//prepare the image to be shown in a `jLabel`
Image Conv1 = (Image)bufferedImage;
ImageIcon Conv2 = new ImageIcon(Conv1);
myLabel.setIcon(Conv2);
I then need to prevent mouse and key events from interacting with the controls on the main window, which are still accessible at the moment, even though they are hidden by the image. I am trying to do this with the following code, but this seems to block only the mouse events:
myLabel.addMouseListener(new MouseAdapter() {});
myLabel.addMouseMotionListener(new MouseMotionAdapter() {});
myLabel.addKeyListener(new KeyAdapter() {});
Iv tried various controls in place of the jLabel
but with the same effect: The mouse is blocked but the keys are not. This is something of a problem because one of the main elements in the app is a jTextPane
which absolutely must not be allowed to accept extraneous key inputs.
For simplicity at the moment I am turning the editable property on and off as required to prevent accidental typing into the text pane, but this is very much a workaround hack because at some point I might have keyboard accelerators assigned and I don't want them being activated by accident when the custom dialog is open.
If anyone has any further suggestions to prevent any keyboard events reaching the underlying controls while the custom dialog is open Id very much like to hear them.
regards
MVK