2012-02-06 54 views
1

我試圖在不包括我的應用程序窗口的情況下捕獲屏幕。爲此,我首先調用setVisible(false),然後調用createScreenCapture方法,最後我調用setVisible(true)。這不起作用,我仍然在屏幕截圖中獲取我的應用程序窗口。如果我添加一個呼叫睡覺這似乎解決了這個問題,但我知道這是不好的做法。什麼是正確的方法來做到這一點?JFrame.setVisible(false)和Robot.createScreenCapture計時

代碼:

setVisible(false); 
BufferedImage screen = robot.createScreenCapture(rectScreenSize); 
setVisible(true); 
+0

注:我已經嘗試過JFrame.repaint()和JFrame.validate()沒有成功。 – Ryan 2012-02-06 21:06:30

回答

1

你不得不推遲通過工具Swing Timer這個動作,例如

import javax.imageio.*; 
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.awt.image.*; 
import java.io.*; 

public class CaptureScreen implements ActionListener { 

    private JFrame f = new JFrame("Screen Capture"); 
    private JPanel pane = new JPanel(); 
    private JButton capture = new JButton("Capture"); 
    private JDialog d = new JDialog(); 
    private JScrollPane scrollPane = new JScrollPane(); 
    private JLabel l = new JLabel(); 
    private Point location; 
    private Timer timer1; 

    public CaptureScreen() { 
     capture.setActionCommand("CaptureScreen"); 
     capture.setFocusPainted(false); 
     capture.addActionListener(this); 
     capture.setPreferredSize(new Dimension(300, 50)); 
     pane.add(capture); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(pane); 
     f.setLocation(100, 100); 
     f.pack(); 
     f.setVisible(true); 
     createPicContainer(); 
     startTimer(); 
    } 

    private void createPicContainer() { 
     l.setPreferredSize(new Dimension(700, 500)); 
     scrollPane = new JScrollPane(l, 
       ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, 
       ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
     scrollPane.setBackground(Color.white); 
     scrollPane.getViewport().setBackground(Color.white); 
     d.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); 
     d.add(scrollPane); 
     d.pack(); 
     d.setVisible(false); 
     d.addWindowListener(new WindowListener() { 

      public void windowOpened(WindowEvent e) { 
      } 

      public void windowClosing(WindowEvent e) { 
       f.setVisible(true); 
      } 

      public void windowClosed(WindowEvent e) { 
      } 

      public void windowIconified(WindowEvent e) { 
      } 

      public void windowDeiconified(WindowEvent e) { 
      } 

      public void windowActivated(WindowEvent e) { 
      } 

      public void windowDeactivated(WindowEvent e) { 
      } 
     }); 
    } 

    private void startTimer() { 
     timer1 = new Timer(1000, new AbstractAction() { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       SwingUtilities.invokeLater(new Runnable() { 

        @Override 
        public void run() { 
         capture.doClick(); 
         f.setVisible(false); 
        } 
       }); 
      } 
     }); 
     timer1.setDelay(500); 
     timer1.setRepeats(false); 
     timer1.start(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     if (e.getActionCommand().equals("CaptureScreen")) { 
      Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // gets the screen size 
      Robot r; 
      BufferedImage bI; 
      try { 
       r = new Robot(); // creates robot not sure exactly how it works 
       Thread.sleep(1000); // waits 1 second before capture 
       bI = r.createScreenCapture(new Rectangle(dim)); // tells robot to capture the screen 
       showPic(bI); 
       saveImage(bI); 
      } catch (AWTException e1) { 
       e1.printStackTrace(); 
      } catch (InterruptedException e2) { 
       e2.printStackTrace(); 
      } 
     } 
    } 

    private void saveImage(BufferedImage bI) { 
     try { 
      ImageIO.write(bI, "JPG", new File("screenShot.jpg")); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void showPic(BufferedImage bI) { 
     ImageIcon pic = new ImageIcon(bI); 
     l.setIcon(pic); 
     l.revalidate(); 
     l.repaint(); 
     d.setVisible(false); 
     //location = f.getLocationOnScreen(); 
     //int x = location.x; 
     //int y = location.y; 
     //d.setLocation(x, y + f.getHeight()); 
     d.setLocation(150, 150); 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       d.setVisible(true); 
      } 
     }); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       CaptureScreen cs = new CaptureScreen(); 
      } 
     }); 
    } 
} 
+0

當!我會'這樣說。猜猜我只需要投票。 ;) – 2012-02-06 23:17:20

+0

在您的代碼中,您正在從事件隊列中調用Thread.sleep。這正是我想要避免的! – Ryan 2012-02-07 20:57:41

+0

@Ryan :-)在這個迴應後,我沒有興趣解釋爲什麼它只能遵循.... – mKorbel 2012-02-07 21:23:15

1

您是否嘗試過使用SwingUtilities.invokeLater()和運行可運行作爲參數傳遞的內部捕捉?我的猜測是,在AWT-EventQueue中的當前事件結束後立即執行重新執行的刪除應用程序,因此立即調用該調用仍會捕獲您的窗口。通過invokeLater在延遲事件中調用createCapture應該可以解決這個問題。

+0

我試過invokeLater,它沒有幫助。 – Ryan 2012-02-07 20:58:34

+0

禁用你的Windows效果,它會像魅力一樣工作,甚至不需要invokelater – 2012-02-09 16:44:25

+0

如果你事先不知道如果動畫(當最小化和最大化窗口時)啓用,那麼你別無選擇,只能使用計時器。僅僅因爲它凍結了用戶的窗口才是邪惡的。 – 2012-02-09 16:53:26