【问题标题】:Is there a way to take a screenshot using Java and save it to some sort of image?有没有办法使用 Java 截取屏幕截图并将其保存到某种图像中?
【发布时间】:2010-09-08 16:02:43
【问题描述】:

正如标题所说的那样简单:你能只使用Java命令来截取屏幕截图并保存吗?或者,我是否需要使用特定于操作系统的程序来截取屏幕截图,然后将其从剪贴板上抓取?

【问题讨论】:

标签: java image screenshot


【解决方案1】:

信不信由你,您实际上可以使用java.awt.Robot 来“创建包含从屏幕读取的像素的图像”。然后,您可以将该图像写入磁盘上的文件。

我刚试了一下,结果是这样的:

Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capture = new Robot().createScreenCapture(screenRect);
ImageIO.write(capture, "bmp", new File(args[0]));

注意:这只会捕获主监视器。有关多显示器支持,请参阅 GraphicsConfiguration

【讨论】:

  • 我想知道这是否是像 Elluminate (elluminate.com) 这样的屏幕共享应用程序使用的。
  • @java_enthu 实际上是的,如果您在应用程序中硬编码截屏路径,则无需控制台即可工作。
  • 机器人在屏幕截图中不包括鼠标。是否有类似的功能可以做完全相同的事情,但是否包括鼠标?
  • 有没有办法捕捉鼠标光标?!
【解决方案2】:

我从不喜欢使用 Robot,所以我自己做了一个简单的方法来制作 JFrame 对象的屏幕截图:

public static final void makeScreenshot(JFrame argFrame) {
    Rectangle rec = argFrame.getBounds();
    BufferedImage bufferedImage = new BufferedImage(rec.width, rec.height, BufferedImage.TYPE_INT_ARGB);
    argFrame.paint(bufferedImage.getGraphics());

    try {
        // Create temp file
        File temp = File.createTempFile("screenshot", ".png");

        // Use the ImageIO API to write the bufferedImage to a temporary file
        ImageIO.write(bufferedImage, "png", temp);

        // Delete temp file when program exits
        temp.deleteOnExit();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}

【讨论】:

  • 你不喜欢机器人有什么原因吗?
  • 把它当作一个品味问题。
  • 看起来这应该具有工作的优势,即使在截屏之前目标窗口被遮挡。
  • 另一方面,它只获取窗口的内容,而Robot 还可以获取窗口的框架和标题栏。
  • 对于 HiDPI (Mac Retina) 显示器,这会以半分辨率创建屏幕截图。在 argFrame.paint(bufferedImage.getGraphics()) 调用之前修复 bufferedImage.getGraphics().scale(2, 2) 并使用 new BufferedImage(rec.width*2, rec.height*2, BufferedImage.TYPE_INT_ARGB)创建 BufferedImage
【解决方案3】:

如果您想捕获所有监视器,可以使用以下代码:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();

Rectangle allScreenBounds = new Rectangle();
for (GraphicsDevice screen : screens) {
    Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();

    allScreenBounds.width += screenBounds.width;
    allScreenBounds.height = Math.max(allScreenBounds.height, screenBounds.height);
}

Robot robot = new Robot();
BufferedImage screenShot = robot.createScreenCapture(allScreenBounds);

【讨论】:

【解决方案4】:
public void captureScreen(String fileName) throws Exception {
   Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
   Rectangle screenRectangle = new Rectangle(screenSize);
   Robot robot = new Robot();
   BufferedImage image = robot.createScreenCapture(screenRectangle);
   ImageIO.write(image, "png", new File(fileName));
}

【讨论】:

    【解决方案5】:
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Rectangle;
    import java.awt.Robot;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.File; 
    import javax.imageio.ImageIO;
    import javax.swing.*;  
    
    public class HelloWorldFrame extends JFrame implements ActionListener {
    
    JButton b;
    public HelloWorldFrame() {
        this.setVisible(true);
        this.setLayout(null);
        b = new JButton("Click Here");
        b.setBounds(380, 290, 120, 60);
        b.setBackground(Color.red);
        b.setVisible(true);
        b.addActionListener(this);
        add(b);
        setSize(1000, 700);
    }
    public void actionPerformed(ActionEvent e)
    {
        if (e.getSource() == b) 
        {
            this.dispose();
            try {
                Thread.sleep(1000);
                Toolkit tk = Toolkit.getDefaultToolkit(); 
                Dimension d = tk.getScreenSize();
                Rectangle rec = new Rectangle(0, 0, d.width, d.height);  
                Robot ro = new Robot();
                BufferedImage img = ro.createScreenCapture(rec);
                File f = new File("myimage.jpg");//set appropriate path
                ImageIO.write(img, "jpg", f);
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }
        }
    }
    
    public static void main(String[] args) {
        HelloWorldFrame obj = new HelloWorldFrame();
    }
    }
    

    【讨论】:

    • 我做了一个基准测试,这个是最慢的,也是最大的损失和最大的文件大小。对不起,
    【解决方案6】:
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();  
    GraphicsDevice[] screens = ge.getScreenDevices();       
    Rectangle allScreenBounds = new Rectangle();  
    for (GraphicsDevice screen : screens) {  
           Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();        
           allScreenBounds.width += screenBounds.width;  
           allScreenBounds.height = Math.max(allScreenBounds.height, screenBounds.height);
           allScreenBounds.x=Math.min(allScreenBounds.x, screenBounds.x);
           allScreenBounds.y=Math.min(allScreenBounds.y, screenBounds.y);
          } 
    Robot robot = new Robot();
    BufferedImage bufferedImage = robot.createScreenCapture(allScreenBounds);
    File file = new File("C:\\Users\\Joe\\Desktop\\scr.png");
    if(!file.exists())
        file.createNewFile();
    FileOutputStream fos = new FileOutputStream(file);
    ImageIO.write( bufferedImage, "png", fos );
    

    bufferedImage 将包含完整的屏幕截图,这是在三台显示​​器上测试的

    【讨论】:

      【解决方案7】:

      你可以使用java.awt.Robot来完成这个任务。

      下面是服务器的代码,它将截取的屏幕截图保存为您的目录中的图像。

      import java.awt.image.BufferedImage;
      import java.io.File;
      import java.io.IOException;
      import java.net.ServerSocket;
      import java.net.Socket;
      import java.net.SocketTimeoutException;
      import java.sql.SQLException;
      import java.text.DateFormat;
      import java.text.SimpleDateFormat;
      import java.util.Date;
      
      import javax.imageio.ImageIO;
      
      public class ServerApp extends Thread
      {
             private ServerSocket serverSocket=null;
             private static Socket server = null;
             private Date date = null;
             private static final String DIR_NAME = "screenshots";
      
         public ServerApp() throws IOException, ClassNotFoundException, Exception{
             serverSocket = new ServerSocket(61000);
             serverSocket.setSoTimeout(180000);
         }
      
      public void run()
         {
             while(true)
            {
                 try
                 {
                    server = serverSocket.accept();
                    date = new Date();
                        DateFormat dateFormat = new SimpleDateFormat("_yyMMdd_HHmmss");
                    String fileName = server.getInetAddress().getHostName().replace(".", "-");
                    System.out.println(fileName);
                    BufferedImage img=ImageIO.read(ImageIO.createImageInputStream(server.getInputStream()));
                    ImageIO.write(img, "png", new File("D:\\screenshots\\"+fileName+dateFormat.format(date)+".png"));
                    System.out.println("Image received!!!!");
                    //lblimg.setIcon(img);
                }
               catch(SocketTimeoutException st)
               {
                     System.out.println("Socket timed out!"+st.toString());
       //createLogFile("[stocktimeoutexception]"+stExp.getMessage());
                        break;
                   }
                   catch(IOException e)
                   {
                        e.printStackTrace();
                        break;
               }
               catch(Exception ex)
              {
                    System.out.println(ex);
              }
            }
         }
      
         public static void main(String [] args) throws IOException, SQLException, ClassNotFoundException, Exception{
                ServerApp serverApp = new ServerApp();
                serverApp.createDirectory(DIR_NAME);
                Thread thread = new Thread(serverApp);
                  thread.start();
         }
      
      private void createDirectory(String dirName) {
          File newDir = new File("D:\\"+dirName);
          if(!newDir.exists()){
              boolean isCreated = newDir.mkdir();
          }
       }
      } 
      

      这是在线程上运行的客户端代码,几分钟后它正在捕获用户屏幕的屏幕截图。

      package com.viremp.client;
      
      import java.awt.AWTException;
      import java.awt.Dimension;
      import java.awt.Rectangle;
      import java.awt.Robot;
      import java.awt.Toolkit;
      import java.awt.image.BufferedImage;
      import java.io.IOException;
      import java.net.Socket;
      import java.util.Random;
      
      import javax.imageio.ImageIO;
      
      public class ClientApp implements Runnable {
          private static long nextTime = 0;
          private static ClientApp clientApp = null;
          private String serverName = "192.168.100.18"; //loop back ip
          private int portNo = 61000;
          //private Socket serverSocket = null;
      
          /**
           * @param args
           * @throws InterruptedException 
           */
          public static void main(String[] args) throws InterruptedException {
              clientApp = new ClientApp();
              clientApp.getNextFreq();
              Thread thread = new Thread(clientApp);
              thread.start();
          }
      
          private void getNextFreq() {
              long currentTime = System.currentTimeMillis();
              Random random = new Random();
              long value = random.nextInt(180000); //1800000
              nextTime = currentTime + value;
              //return currentTime+value;
          }
      
          @Override
          public void run() {
              while(true){
                  if(nextTime < System.currentTimeMillis()){
                      System.out.println(" get screen shot ");
                      try {
                          clientApp.sendScreen();
                          clientApp.getNextFreq();
                      } catch (AWTException e) {
                          // TODO Auto-generated catch block
                          System.out.println(" err"+e);
                      } catch (IOException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                      } catch(Exception e){
                          e.printStackTrace();
                      }
      
                  }
                  //System.out.println(" statrted ....");
              }
      
          }
      
          private void sendScreen()throws AWTException, IOException {
                 Socket serverSocket = new Socket(serverName, portNo);
                   Toolkit toolkit = Toolkit.getDefaultToolkit();
                   Dimension dimensions = toolkit.getScreenSize();
                       Robot robot = new Robot();  // Robot class 
                       BufferedImage screenshot = robot.createScreenCapture(new Rectangle(dimensions));
                       ImageIO.write(screenshot,"png",serverSocket.getOutputStream());
                       serverSocket.close();
          }
      }
      

      【讨论】:

        【解决方案8】:

        Toolkit 根据 PPI 返回像素,因此在 Windows 中使用 PPI> 100% 时不会为整个屏幕创建屏幕截图。 我建议这样做:

        DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getDisplayMode();
        Rectangle screenRectangle = new Rectangle(displayMode.getWidth(), displayMode.getHeight());
        BufferedImage screenShot = new Robot().createScreenCapture(screenRectangle);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-04-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-23
          相关资源
          最近更新 更多