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ść.
Poniżej znajdziesz dodatkowo kod z filmu u góry tej strony.
import java.awt.*;
import java.awt.event.InputEvent;
public class Main {
public static void main(String[] args) throws AWTException, InterruptedException {
Robot robot = new Robot();
Color green = new Color(75, 219, 106);
int x = 500;
int y = 400;
while (true) {
Color pixelColor = robot.getPixelColor(x, y);
if(pixelColor.equals(green)) {
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
}
}
}
}
Dyskusja i komentarze
Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.
Poniżej znajdziesz archiwalne wpisy z czasów, gdy strona była jeszcze hobbystycznym blogiem.
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).
walden
Mi bez Release w konsoli cmd wyświetlało tylko 'helo world' - zjadało jedną literkę 'l', w notatniku normalnie.
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...
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"));