JFrame 和可见性:淡出和获取屏幕截图的问题

Posted

技术标签:

【中文标题】JFrame 和可见性:淡出和获取屏幕截图的问题【英文标题】:JFrame and visibility: issue with fading out and getting a screenshot 【发布时间】:2013-06-15 19:07:49 【问题描述】:

在通过按下部署到JFrame 中的按钮执行的操作(即方法)中,我想隐藏 java 应用程序,然后获取屏幕截图。最后,截屏后,我需要让JFrame 可见。

方法如下:

  public void myButtonPressedAction()
       //Hiding the JFrame
       this.setVisible(false);
       //Now I use Robot to get a screenshot using another method
       //not reported for simplicity
       myMethodToGetScreenshot();
       //Making the JFrame visible
       this.setVisible(true);
  

发生的情况是,一旦可见性设置为 false,应用程序开始变得不可见,我立即得到屏幕截图:不幸的是,屏幕截图还在淡出时捕获了 JFrame(即,它将变得不可见,isVisible 方法返回true,但JFrame 并非完全不可见)。

一种可能的解决方案是插入一个计时器,在对setVisible(false) 的调用和对myMethodToGetScreenshot() 的调用之间设置一个延迟。但是,假设系统很忙,延迟可能会被低估;相反,更大的延迟会使我的应用程序变慢!

我怎样才能得到确切的时间,使JFrame 完全淡出,即它真的不可见?

编辑

这是在构造函数中初始化的:

String myPath= ...;//here I have a String that represent a path to a folder.
JPEGImageWriteParam JPEG_PARAMS_BEST_QUALITY = new JPEGImageWriteParam(null);
JPEG_PARAMS_BEST_QUALITY.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
JPEG_PARAMS_BEST_QUALITY.setCompressionQuality(1f);

这是myMethodToGetScreenshot()的代码:

public void  myMethodToGetScreenshot()
  BufferedImage capture = new Robot().createScreenCapture(screenArea);
  ImageWriter writer = writerService.getWriter();
  writer.setOutput(new FileImageOutputStream(new File(myPath+"screenshot.jpg")));
  writer.write(null, new IIOImage(capture, null, null), JPEG_PARAMS_BEST_QUALITY);

这是我得到的屏幕截图。你可以看到 JFrame 淡出...

【问题讨论】:

【参考方案1】:

你可以使用setExtendedState代替setvisible

//Minimize the JFrame
this.setExtendedState(JFrame.ICONIFIED);
//Now I use Robot to get a screenshot using another method
//not reported for simplicity
myMethodToGetScreenshot();
//Restore the JFrame
this.setExtendedState(JFrame.NORMAL);

【讨论】:

正如我所说,在调用setVisible(false) 之后,isVisible 方法返回true 没有任何改变!屏幕截图在淡出时仍然捕获 JFrame。我不知道褪色是Java控制器还是操作系统控制器! I don't know if the fading is controller by Java or by the OS!..它由操作系统控制。查看我的更新..我希望这对你有帮助 太棒了!这个解决方案真的很聪明!【参考方案2】:

然后放一些延迟时间。你可以使用Swing timer。

这是一个小演示:

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class ScreenshotDemo 
    JFrame frame = new JFrame();
    JButton button = new JButton("Catch the screenshot");
    Timer timer;
    Robot robot;
    JLabel label = new JLabel();

    public ScreenshotDemo() 
        try 
            robot = new Robot();
         catch (AWTException e1) 
            e1.printStackTrace();
        

        // Keeps frame disposed for 3 seconds
        timer = new Timer(3000, new ActionListener() 
            @Override
            public void actionPerformed(ActionEvent e) 
                Rectangle size = new Rectangle(Toolkit.getDefaultToolkit()
                        .getScreenSize());
                Image image = robot.createScreenCapture(size);
                label.setIcon(new ImageIcon(image));
                frame.setVisible(true);
            
        );
        timer.setRepeats(false);

        button.addActionListener(new ActionListener() 
            @Override
            public void actionPerformed(ActionEvent arg0) 
                frame.setVisible(false);
                timer.start();
            
        );

        frame.add(button, BorderLayout.NORTH);
        frame.add(label, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        // frame.pack();
        frame.setSize(1024, 768);
        frame.setVisible(true);
    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 
            @Override
            public void run() 
                new ScreenshotDemo();
            
        );
    


基本上,您将隐藏框架一段时间(在此演示中为 3 秒)。当框架被隐藏时,您将拍摄快照。

【讨论】:

这是我想到的第一个解决方案,您可以从我的问题中读到。正如我所指出的,这种方法有一些缺点。不过,谢谢! @mat_boy 这是一个可行的解决方案,我刚刚测试过。只需将您的代码放入 Timers actionPerformed 方法(在 frame.setVisible(true) 之前),瞧! +1 表示努力。我认为Gabriel Negut 的答案更优雅。不是吗?【参考方案3】:

您必须在隐藏框架之后和截取屏幕截图之前添加一个合理的延迟。最简单的方法是在robot.createScreenCapture() 之前插入对robot.delay() 的调用。

【讨论】:

我刚刚说过,使用时间是一种可能的解决方案,我会避免这种情况(想象一下当机器忙碌并因此变慢时会发生什么)。但是,您的答案与brano88 提供的答案相似,但更紧凑。我喜欢! +1 表示答案的简洁性。如果没有人会在不使用时间的情况下回答这个问题,我会接受这个!【参考方案4】:

我会尝试 ComponentListener(假设此代码转到 JFrame 扩展类的成员):

    final Container contentPane = getContentPane();
    ComponentAdapter componentAdapter = new ComponentAdapter() 

        @Override
        public void componentHidden(ComponentEvent arg0) 
            myMethodToGetScreenshot();
            contentPane.removeComponentListener(this);
        
    ;
    contentPane.addComponentListener(componentAdapter);

【讨论】:

以上是关于JFrame 和可见性:淡出和获取屏幕截图的问题的主要内容,如果未能解决你的问题,请参考以下文章

淡入/淡出的简单切换不适用于过渡、不透明度和可见性

android 怎么获取当前屏幕的截图

Android录屏应用开发研究

C语言 服务项进行全屏幕截图 但是截图后是黑屏怎么办?

在全屏模式下收听状态栏/导航栏可见性?

如何在JFrame中刷新图像?