2

我正在试验Java和 GUI 操作,我有一个自定义对话框,它是从一个jPanel富有想象力的DLog创建的,它根据请求出现以收集用户输入。这工作正常,但当然我的对话框不是模态的,这使得其余控件在对话框打开时对用户可见和可访问。一点都不好!

为了克服这个问题,我有一个单独的jPanel称为DLogCover的窗口大小,但在需要之前它是不可见的。当自定义对话框显示时,我的窗口的屏幕截图被拍摄并显示为DLogCover上标签中的图像,该图像显示在我的自定义对话框下方,但高于其他所有内容(在MODAL_LAYERa 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;
}

当我打开我的自定义对话框时调用它,然后我可以修改图像以使其变暗并稍微模糊,然后将其显示jLabel在我的自定义DLogCover上存在的 a 中(这只是图像的 ajPanel和 a 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() {});

iv 尝试了各种控件来代替,jLabel但效果相同:鼠标被阻止但按键没有。这是一个问题,因为应用程序中的主要元素之一是jTextPane绝对不允许接受无关的键输入。

为简单起见,目前我正在根据需要打开和关闭可编辑属性以防止意外键入文本窗格,但这在很大程度上是一种解决方法,因为在某些时候我可能分配了键盘加速器并且我不想要它们打开自定义对话框时意外激活。

如果有人有任何进一步的建议来防止在自定义对话框打开时任何键盘事件到达底层控件,我非常希望听到它们。

问候

MVK

4

1 回答 1

1

我强烈建议您查看 JXLayer 项目。它完全符合您的要求。

另外,请查看http://www.jhlabs.com/ip/filters/index.html上的 JHLabs-Filters 。

如果您仍然一头雾水,您可以获取内容窗格的大小并从主框架的高度中减去它。这应该(通常)给你你想要的结果。

你需要做类似的事情

Point pos = ((JComponent)frame.getContentPane()).getLocationOnScreen();
Point fPos = frame.getLocation();

这将允许您计算框架内内容窗格的偏移量,您可以从那里进行调整。

就个人而言,我只想研究 JXLayer。

谢恩

更新:

好吧,艰难的路。所以你已经捕获了屏幕。正如我上面建议的那样,您将需要修剪框架的边框。

使用 JHLabs-Filters,可以对图像进行如下模糊处理

GaussianFilter gf = new GaussianFilter(10);
imgBG = gf.filter(imgBG, null);

要完成鼠标事件处理程序,您将需要使用“玻璃窗格”。这只是一个您可以放置​​在框架顶部的组件,将鼠标侦听器(和键侦听器)附加到它,它们应该为您“使用”事件。

查找 JFrame.getGlassPane()。基本上,您希望将用于绘制背景(并将对话框置于其上)的组件添加到此(不要忘记使其可见)。

这可能会在这方面对您有所帮助http://www.java2s.com/Code/Java/Swing-JFC/Showhowaglasspanecanbeusedtoblockmouseandkeyevents.htm

希望对谢恩有所帮助

于 2012-07-10T05:43:27.657 回答