JFrame不会及时消失以截取屏幕截图

时间:2015-02-18 20:33:16

标签: java swing

此实用程序应用程序通过按JFrame上的按钮获取多个监视器的屏幕截图。该方法的预期逻辑如下:

  • 创建新的Rectangle以表示所有监视器的boundsm
  • 的并集
  • 使用InvokeAndWait隐藏到JFrame,并确保在进一步处理之前隐藏它
  • 使用Robot类
  • 截取屏幕截图
  • 再次将帧设置为可见并返回图像

即使最终的“返回框架可见”步骤已从代码中注释掉,让我在执行后看不到屏幕上的框架,框架在屏幕截图中可见。我不知道为什么。

使用print语句,我已经确定在获取屏幕截图之前,触发JFrame不可见方法的触发器会运行。在尝试截屏之前,我还尝试使用if语句检查JFrame是否可见,并且if语句从未被触发。

这是什么解决方案?

public Image capture(ArrayList<Monitor> monitors) {

    Rectangle bounds = new Rectangle();
    monitors.stream().forEach(a -> Rectangle.union(bounds, a.getBounds(), bounds) );

    Image image = null;

    try {

        EventQueue.invokeAndWait(() ->  {
            frame.setVisible(false);
            System.out.println("Set frame invisible");
        });

    } catch (Exception ex) {
        ex.printStackTrace();
    }

    try {

        image = new Image(new Robot().createScreenCapture(bounds));

    } catch (Exception ex) {
        ex.printStackTrace();           
    }

    //frame.setVisible(true);
    return image;
}

1 个答案:

答案 0 :(得分:1)

这不是一个明确的答案,但也许它会指出你正确的方向。

我遇到类似的问题,要求JFrame使用OpenGL在3D应用程序上全屏显示。

我假设发生的事情是frame.setVisible()与OS窗口管理器对话,请求隐藏(或显示)窗口。一旦发出请求并确认,方法调用就不再阻塞,invokeAndWait()中的线程现在完成了调用和等待。

您的代码将继续截屏,但不保证操作系统实际上已经处理了最小化Window的请求。在你的情况下,似乎没有。

解决方案(也许?): 看起来Java有一个名为WindowEvent doc here的类。您应该能够在等待状态更新的屏幕截图调用之前创建侦听器和/或循环。请注意该文档具体说:

  

窗口已停用的事件类型。当Window不再是活动窗口时,将传递此事件。只有一个框架或一个对话框可以是活动窗口。 本机窗口系统可以表示活动窗口或具有特殊装饰的子窗口,例如突出显示的标题栏。活动窗口始终是聚焦窗口,或者是聚焦窗口所有者的第一个框架或对话框。

我怀疑等待WINDOW_DEACTIVATED和/或WINDOW_LOST_FOCUS可能是操作系统窗口管理器是否已最小化窗口的实际指示。

同样,我基于几个月前我工作的一个大多数不相关的项目,但希望其中一些有用。

<强>更新

OP实施了如下解决方案:

public Image capture(ArrayList<Monitor> monitors) 
{

    Rectangle bounds = new Rectangle();
    monitors.stream().forEach(a -> Rectangle.union(bounds, a.getBounds(), bounds) );

    Image image = null;

    try 
    {

        EventQueue.invokeAndWait(() -> frame.setExtendedState(Frame.ICONIFIED));

        while (frame.getExtendedState() != Frame.ICONIFIED) { }
        image = new Image(new Robot().createScreenCapture(bounds));

    } 
    catch (Exception ex) 
    {
        ex.printStackTrace();           
    }

    EventQueue.invokeLater(() -> frame.setExtendedState(Frame.NORMAL));

    return image;
}