Gibt es eine Möglichkeit, einen Screenshot mit Java aufzunehmen und in einem Bild zu speichern?

128

Einfach wie der Titel schon sagt: Können Sie nur Java-Befehle verwenden, um einen Screenshot aufzunehmen und zu speichern? Oder muss ich ein betriebssystemspezifisches Programm verwenden, um den Screenshot aufzunehmen und ihn dann aus der Zwischenablage zu holen?

jjnguy
quelle
Ich hätte nie gedacht, dass es so einfach sein würde.
jjnguy
2
Dank dieser Frage schrieb ich ein Tutorial für absolute Anfänger in meinem Blog: thepcwizard.in/2012/12/java-screen-capturing-tutorial.html
ThePCWizard

Antworten:

187

Ob Sie es glauben oder nicht, Sie können tatsächlich verwenden, java.awt.Robotum "ein Bild mit Pixeln zu erstellen, die vom Bildschirm gelesen werden". Sie können dieses Bild dann in eine Datei auf der Festplatte schreiben.

Ich habe es gerade versucht und das Ganze endet wie folgt:

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

HINWEIS: Dadurch wird nur der primäre Monitor erfasst. Informationen zur Unterstützung mehrerer Monitore finden Sie unter GraphicsConfiguration .

David Citron
quelle
1
Ich frage mich, ob dies für Bildschirmfreigabeanwendungen wie Elluminate ( elluminate.com ) verwendet wird.
Chris Wagner
@java_enthu eigentlich ja, es wird ohne Konsole funktionieren, wenn Sie den Pfad zum Screenshot in Ihrer App fest codieren.
Dmitry Zagorulkin
2
Der Roboter bezieht die Maus nicht in die Bildschirmaufnahme ein. Gibt es eine ähnliche Funktion, die genau dasselbe tut, aber die Maus einschließt?
nullUser
3
Gibt es eine Möglichkeit, auch den Mauszeiger zu erfassen ?!
Mehdi Karamosly
23

Ich habe Robot nie gemocht, deshalb habe ich meine eigene einfache Methode zum Erstellen von Screenshots von JFrame-Objekten erstellt:

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();
    }
}
DejanLekic
quelle
17
Gibt es einen Grund, warum Sie Robot nicht mögen?
Simon Forsberg
2
Betrachten Sie es einfach als Geschmackssache.
DejanLekic
3
Es sieht so aus, als ob dies den Vorteil haben sollte, auch dann zu funktionieren, wenn das Zielfenster vor der Aufnahme des Screenshots verdeckt ist.
Brad Mace
7
Auf der anderen Seite erhält dies nur den Inhalt des Fensters, während RobotSie mit ihm auch den Rahmen und die Titelleiste des Fensters erhalten können.
Brad Mace
1
Bei HiDPI-Displays (Mac Retina) werden Screenshots mit halber Auflösung erstellt. Um dieses Problem mit bufferedImage.getGraphics (). Scale (2, 2) vor dem Aufruf von argFrame.paint (bufferedImage.getGraphics ()) zu beheben, verwenden Sie das neue BufferedImage (rec.width * 2, rec.height * 2, BufferedImage.TYPE_INT_ARGB) Erstellen Sie das BufferedImage
Nyholku
18

Wenn Sie alle Monitore erfassen möchten, können Sie den folgenden Code verwenden:

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);
11101101b
quelle
4
wäre besser, es so
Brad Mace
10
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));
}
user2503881
quelle
3
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();
}
}
Nilesh Jadav
quelle
Ich habe einen Benchmark durchgeführt und dieser ist der langsamste, hat auch den größten Verlust und die größte Dateigröße. Entschuldigung,
Liam Larsen
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);
       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 enthält einen vollständigen Screenshot, der mit drei Monitoren getestet wurde

Joe Pelletier
quelle
0

Sie können verwenden java.awt.Robot , um diese Aufgabe zu erreichen.

Unten finden Sie den Code des Servers, der den aufgenommenen Screenshot als Bild in Ihrem Verzeichnis speichert.

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();
    }
 }
} 

Und dies ist Client-Code, der auf einem Thread ausgeführt wird und nach einigen Minuten den Screenshot des Benutzerbildschirms aufzeichnet.

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();
    }
}
Muhammad Yawar
quelle
0

Das Toolkit gibt Pixel basierend auf PPI zurück. Daher wird bei Verwendung von PPI> 100% in Windows nicht für den gesamten Bildschirm ein Screenshot erstellt. Ich schlage vor, dies zu tun:

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