Kurs Java Podstawy - rozszerzony

Klasa Robot

Z pewnością nie raz byliście w sytuacji, że chcielibyście napisać program, który sam wykonuje jakieś czynności na waszym komputerze - porusza kursorem, wypisuje jakiś tekst. Mogłoby się wydawać, że jest to skomplikowane i wymaga sięgnięcia po jakieś skomplikowane biblioteki, a tymczasem służy do tego jedna klasa - Robot. Możemy dzięki niej w bardzo prosty sposób obsługiwać klawiaturę oraz mysz, a także robić screenshoty i odczytywać informacje o pikselach.

Nie trudno sobie wyobrazić jak wielkie możliwości nam to daje - bez problemu można napisać prosty tasker, bota do gry, a nawet prostą wersję team viewera, lub program do zdalnego sterowania pulpitem.

Najciekawsze metody, które znajdziemy w klasie Robot to:

  • keyPress(int keycode), keyRelease(int keycode) - wciśnięcie/zwolnienie klawisza na klawiaturze. Niestety minus jest taki, że keycode nie odpowiada wartości ASCII danego znaku trzeba się posługiwać wartościami stałych zdefiniowanych w klasie KeyEvent
  • mousePress(int buttons), mouseRelease(int buttons) - wciśnięcie/zwolnienie przycisków myszy - jako argumenty podajemy stałe zdefiniowane w klasie InputEvent (BUTTON1_MASK, BUTTON2_MASK, BUTTON3_MASK)
  • mouseMove(int x, int y) - przesunięcie kursora we wskazany punkt ekranu
  • createScreenCapture(Rectangle screenRect) - zrobienie screenshota ekranu w wybranym obszarze
  • delay(int time) - wstrzymanie wykonywanego wątku na czas podany jako argument (w milisekundach)

Oprócz tego klasa Robot zawiera kilka innych metod - ale nie będziemy się nimi zajmować, zainteresowani mogą je zobaczyć w dokumentacji.

Zobaczmy prosty przykład tego jak można ją wykorzystać w jakimś przykładzie. Napiszmy program, który napisze używając klawiatury "Hello World", następnie wykona screena ekranu i zapisze go na dysku. - jest na tyle prosty, że wszystko zmieści nam się w jednej klasie.

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class RobotTest {
	Robot robot;

	public RobotTest() {
		try {
			robot = new Robot();
		} catch (AWTException e) {
			System.err.println("Co ten robot wyprawia?!");
			e.printStackTrace();
		}
	}

	/**
	 * Metoda drukuje tekst "Hello World"
	 */
	public void printText() {
		int[] text = {KeyEvent.VK_H, KeyEvent.VK_E, KeyEvent.VK_L, KeyEvent.VK_L, KeyEvent.VK_O, KeyEvent.VK_SPACE,
				KeyEvent.VK_W, KeyEvent.VK_O, KeyEvent.VK_R, KeyEvent.VK_L, KeyEvent.VK_D};
		//pętla - wciśnięcie przycisku i przerwa na 200ms
		for(int i=0; i<text.length; i++) {
			robot.keyPress(text[i]);
			robot.delay(200);
		}
	}

	/**
	 * Metoda robi screenshot ekranu i zapisuje go na dysku
	 */
	public void screenCapture() {
		//pobieramy rozmiar ekranu i tworzymy Rectangle
		Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
		Rectangle rectangle = new Rectangle(dimension);
		//robimy screenshot z utworzonego obszaru
		BufferedImage screen = robot.createScreenCapture(rectangle);
		try {
			ImageIO.write(screen, "jpg", new File("screenshot.jpg"));
		} catch (IOException e) {
			System.err.println("Błąd zapisu obrazu");
			e.printStackTrace();
		}
	}

	/**
	 * Testujemy czy działa
	 */
	public static void main(String[] args) {
		RobotTest test = new RobotTest();
		test.robot.delay(3000);
		test.printText();
		test.screenCapture();
	}

}

Przykład w zasadzie ma odpowiednie komentarze więc nie ma wiele do omówienia. Stworzyliśmy dwie metody odpowiedzialne za funkcje programu: printText(), które wydrukuje nam "Hello World", screenCapture(), która zrobi zrzut ekranu. Dodatkowo wykorzystano metodę delay() z klasy Robot, aby wstrzymać działanie programu - najpierw na 3 sekundy przed wydrukowaniem tekstu (abyśmy mogli sobie np kliknąć w notatniku i zobaczyli, że faktycznie napis się tam będzie pojawiał), a później na 200 milisekund pomiędzy kolejnymi "wciśnięciami" klawiszy.

W przypadku przechwytywania obrazu z pulpitu najpierw pobieramy rozmiar ekranu przy pomocy getScreenSize() klasy Toolkit (zawiera ona także dużo innych ciekawych informacji systemowych). Obraz możemy też zapisać w formacie .png zmieniając rozszerzenie w metodzie write z klasy ImageIO - powinniśmy wtedy uzyskać lepszą jakość.

Klasa robot w javie

Komentarze

del

Genialne! Dzięki wielkie, jak możesz to rozbudować to czekam z niecierpliwością, Ewentualnie możesz podać inne tego typu ciekawostki dotyczące Javy? Chętnie poczytam. Pozdrawiam.

darQ

Myślę, że po wciśnięciu przycisku należałoby jeszcze go puścić ;) Zaraz pod kodem ze wciśnięciem można śmiało dodać puszczenie takiego przycisku. Czyli...

...
for(int i=0; i<text.length; i++) {
robot.keyPress(text[i]);
robot.keyRelease(text[i]); // DODANY RELASE !
robot.delay(200);
}
...

Dlaczego? Jedna JVM drugiej nie równa i mogą się różne rzeczy dziać ;)

fsdfsdf

Nie działa na przeglądarkach(np. wciśnięcie buttona). Wie ktoś jak zrobić, aby działało?

darQ

Użyłem dwóch (DWÓCH) metod: wciśnięcie i zwolnienie przycisku i... działa. W przeglądarce. Na buttonach, w obiektach flashowych itp.

Sprecyzuj problem.

P.S. Najprostszy przykład - gdy element znajduje się w pozycji 500,400 od lewego górnego rogu ekranu:
...
Thread.sleep(4000); // Daj sobie czas na alt+taba do przeglądarki (oczywiście 'sen' w try-catch'u)
robot.mouseMove(500, 400); //Przesuwamy myszkę
robot.mousePress(MouseEvent.BUTTON1_MASK); // Wciskami button 1
robot.mouseRelease(MouseEvent.BUTTON1_MASK); // Puszczamy button 1
...

Sławek Ludwiczak

Bez Release też powinno działać, bo napisałem w ten sposób bota, który wygrał w konkursie nagrodę ;) Chociaż jak najbardziej warto ją dodać i dzięki za zwrócenie uwagi (warto też dodać krótki delay pomiędzy tymi operacjami).

Jareczek234124

sraka na uho fotomontasz

walden

Mi bez Release w konsoli cmd wyświetlało tylko 'helo world' - zjadało jedną literkę 'l', w notatniku normalnie.

Mikolaj

Witam, a czy jest możliwość zrobienia funkcji piszącej tekst, ale podany w nawiasie?
np. public void pisz(string tekst){
//kod
}

Sławek Ludwiczak

oczywiście, że jest. Nie wiem tylko w czym konkretnie masz problem :)

barwnikk

keyPress naciska i spuszcza klawisz. A jak zrobić, aby przytrzymało mi spacje przez 5 sek? to mi nie działa:
Robot r = new Robot();
r.keyPress(KeyEvent.VK_SPACE);
r.delay(5000);
r.keyRelease(KeyEvent.VK_SPACE);

W programie (notatniku) tylko widać jedną spację, ale shift trzyma...

rajczek

Hej. Program po napisaniu "hello world" zatrzymuje się, a konsola nie wyświetla "błąd w zapisie obrazu". Wiecie może dlaczego?

bartesk

Tez to miale. pomoglo jak przy zapisywaniu obrazu wpisalem konkretny adres np. "D://screenshot.jpg"

ImageIO.write(screen, "jpg", new File("D://screenshot.jpg"));