【发布时间】:2012-07-09 00:21:15
【问题描述】:
我正在尝试Java 和 GUI 操作,我有一个自定义对话框,该对话框是从 jPanel 创建的,想象中称为 DLog,它会根据请求显示以收集用户输入。这很好用,但是我的对话框当然不是模态的,这使得其余控件在对话框打开时对用户可见和可访问。一点都不好!
为了克服这个问题,我有一个单独的jPanel,称为 DLogCover,它的大小与窗口一致,但在需要之前它是不可见的。当自定义对话框显示时,我的窗口的屏幕截图被拍摄并显示为 DLogCover 上标签中的图像,该标签显示在我的自定义对话框下方,但高于其他所有内容(在 MODAL_LAYER 的jLayeredPanel - 自定义对话框出现在 POPUP_LAYER)。这完全按计划进行,尽管有两个琐碎的问题希望您能提供帮助。
首先截图当然包括标题栏和窗口的左边框。我已经考虑到这一点,使用了现在对我有用的任意数字,但当然这在每个操作系统上都会有所不同,因为我使用的是系统外观和感觉,这些大小可能不正确。
问题:有什么方法可以确保我的屏幕截图只是我的窗口的内部内容(或任何方法来始终获得窗口标题栏和边框的正确大小,与操作系统无关)?
其次,虽然我的屏幕截图效果很好,但它只是一个窗口的图像,我想让它稍微褪色或模糊,以使它看起来确实有东西覆盖了控件。
问题:有什么方法可以操纵图像来呈现这种外观?
这是我用来捕获图像并显示它的代码(在显示自定义对话框之前):
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
非常感谢您提供的任何帮助,和以前一样,我这样做的原因是因为我正在努力学习Java,所以我正在尝试,目前就是这样!
非常感谢您提供的任何帮助,当然我愿意接受有关实现相同目标的替代方法的建议。
一些答案
我想添加此信息,以便任何其他人可以找到它。
感谢 Andrew Thompson 的代码(非常感谢 nIcE cOw 提供的链接)我现在可以获取窗口内容的屏幕截图,无需尝试计算标题栏和边框大小:
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;
}
当我打开我的自定义对话框时会调用它,然后我可以修改图像以使其变暗并稍微模糊,然后将其显示在我的自定义 DLogCover 上存在的 jLabel 中(这只是图像的jPanel 和jLabel):
//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);
然后我需要阻止鼠标和键事件与主窗口上的控件交互,这些控件目前仍然可以访问,即使它们被图像隐藏了。我正在尝试使用以下代码执行此操作,但这似乎只阻止鼠标事件:
myLabel.addMouseListener(new MouseAdapter() {});
myLabel.addMouseMotionListener(new MouseMotionAdapter() {});
myLabel.addKeyListener(new KeyAdapter() {});
我尝试了各种控件来代替jLabel,但效果相同:鼠标被阻止但按键没有。这是一个问题,因为应用程序中的主要元素之一是jTextPane,绝对不允许它接受无关的键输入。
目前为了简单起见,我正在根据需要打开和关闭可编辑属性,以防止意外键入文本窗格,但这在很大程度上是一种解决方法,因为在某些时候我可能分配了键盘加速器而我没有'不希望它们在自定义对话框打开时被意外激活。
如果有人有任何进一步的建议,以防止在自定义对话框打开时任何键盘事件到达底层控件,我非常希望听到它们。
问候
MVK
【问题讨论】:
-
请看看@AndrewThompson 的这个精彩的example :-)。但是如何为图像添加效果超出了我的知识范围,因此无法阐明该主题:(。此线程包含一些simple examples
-
感谢nIcE cOw,安德鲁斯代码成功获得了我需要的图像(减去边框和标题栏等),但现在又打开了另一个蠕虫罐!我会更新我的问题以反映这一点。非常感谢您的链接。
-
你很受欢迎,保持微笑:-)