java机器人源码
  tjCN0TA76tF8 2023年11月02日 46 0

简介:此类用于生成本机系统输入事件,出于测试自动化、自运行演示和其他可以控制鼠标和键盘的应用程序这是需要的。机器人的主要目的是方便用户Java平台实现的自动化测试


方法介绍及解析:以下private开头方法为Robot内部使用,方法,public方法为对外开放方法,请重点关注public方法


Robot中对外提供接口


使用要点


代码示例


说明


1.实例化方法


new Robot();


无参实例化,详见1


new Robot(


GraphicsEnvironment.getLocalGraphicsEnvironment()

   .getDefaultScreenDevice());

1.

2.

带参实例化,详见2


2.屏幕截图


Robot robot = new Robot();  //初始化Robot对象


   Rectangle rect = new Rectangle(0, 0, 50, 50);  //构建范围


   BufferedImage buffer = robot.createScreenCapture(rect); //截取


详见17,截取固定区域屏幕图片


3.延时休眠


robot.delay(1000);


//延时1秒,详见23


4.键盘模拟


robot.keyPress(KeyEvent.VK_A);


按下A键,键盘上所有按键的ASCII码都在KeyEvent中定义了静态常量


robot.keyRelease(KeyEvent.VK_A);


弹起A键


5.鼠标模拟


robot.mouseMove(10,20);


将鼠标移动至(10,20)这个坐标点


robot.mousePress(InputEvent.BUTTON1_MASK);//左键


robot.mousePress(InputEvent.BUTTON2_MASK);//中键(早期鼠标才有,已被滚轮替代)


robot.mousePress(InputEvent.BUTTON3_MASK)//右键


鼠标按下事件


robot.mouseRelease(InputEvent.BUTTON1_MASK);//左键


robot.mouseRelease(InputEvent.BUTTON2_MASK);//中键(早期鼠标才有,已被滚轮替代)


robot.mouseRelease(InputEvent.BUTTON3_MASK)//右键


鼠标弹起事件


robot.mouseWheel(key);


鼠标滚轮事件,详见12


1.Robot无参构造方法:此方法作用是在主屏幕构建机器人对象。GraphicsEnvironment.isHeadless()此方法是测试当前服务器鼠标键盘是否支持GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice(),其中GraphicsEnvironment.getLocalGraphicsEnvironment()为获取当前系统环境,getDefaultScreenDevice为获取默认屏幕设备


init方法为将此屏幕初始化进Robot对象中,iinit()方法详解见下文第3点


public Robot() throws AWTException {

       if (GraphicsEnvironment.isHeadless()) {

           throw new AWTException("headless environment");

       }

       init(GraphicsEnvironment.getLocalGraphicsEnvironment()

           .getDefaultScreenDevice());

   }

1.

2.

3.

4.

5.

6.

7.

2.Robot带参构造方法:此方法作用为给定屏幕创建机器人对象(注意此方法重点,实现钩子函数必须掌握,可在后台运行得点击脚本会依赖此方法)


checkIsScreenDevice:检查screen是否为屏幕设备


init方法为将此屏幕初始化进Robot对象中,init()方法详解见下文第3点


public Robot(GraphicsDevice screen) throws AWTException {

       checkIsScreenDevice(screen);

       init(screen);

   }

1.

2.

3.

4.

3.init方法:初始化屏幕,将屏幕写入服务内存中


checkRobotAllowed:检查当前设备安全策略是否允许创建机器人


Toolkit toolkit = Toolkit.getDefaultToolkit();//获取默认工具箱,此方法加入synchronized标识,即为线程安全,判断Toolkit是否为ComponentFactory工具包


初始化RobotPeer


初始化机器人处理器RobotDisposer


sun.java2d.Disposer.addRecord(anchor, disposer);//将机器人处理器加入window系统处理器中,此代码含义是执行调用windows底层处理器


initLegalButtonMask:初始化鼠标按钮掩码,详见第4点


private void init(GraphicsDevice screen) throws AWTException {

       checkRobotAllowed();

       Toolkit toolkit = Toolkit.getDefaultToolkit();

       if (toolkit instanceof ComponentFactory) {

           peer = ((ComponentFactory)toolkit).createRobot(this, screen);

           disposer = new RobotDisposer(peer);

           sun.java2d.Disposer.addRecord(anchor, disposer);

       }

       initLegalButtonMask();

   }

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

 4.initLegalButtonMask:初始化合法的鼠标按钮掩码(所谓掩码即为ASCII码)。


判定按钮使用标识LEGAL_BUTTON_MASK,0为默认未使用,1为已使用

判定默认工具箱中是否允许处理和发布额外的鼠标按钮事件

获取鼠标按钮数

将鼠标按钮值做位或运算,并存入tmpMask中

private static synchronized void initLegalButtonMask() {

       if (LEGAL_BUTTON_MASK != 0) return;


       int tmpMask = 0;

       if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){

           if (Toolkit.getDefaultToolkit() instanceof SunToolkit) {

               final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();

               for (int i = 0; i < buttonsNumber; i++){

                   tmpMask |= InputEvent.getMaskForButton(i+1);

               }

           }

       }

       tmpMask |= InputEvent.BUTTON1_MASK|

           InputEvent.BUTTON2_MASK|

           InputEvent.BUTTON3_MASK|

           InputEvent.BUTTON1_DOWN_MASK|

           InputEvent.BUTTON2_DOWN_MASK|

           InputEvent.BUTTON3_DOWN_MASK;

       LEGAL_BUTTON_MASK = tmpMask;

   }

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

5.checkRobotAllowed:判定当前设备的安全策略机制


获取当前系统安全管理器

检测安全管理器是否允许创建Robot机器人

private void checkRobotAllowed() {

       SecurityManager security = System.getSecurityManager();

       if (security != null) {

           security.checkPermission(SecurityConstants.AWT.CREATE_ROBOT_PERMISSION);

       }

   }

1.

2.

3.

4.

5.

6.

6.checkIsScreenDevice:检测屏幕设备。检测device是否是一个屏幕设备


private void checkIsScreenDevice(GraphicsDevice device) {

       if (device == null || device.getType() != GraphicsDevice.TYPE_RASTER_SCREEN) {

           throw new IllegalArgumentException("not a valid screen device");

       }

   }

1.

2.

3.

4.

5.

7.RobotDisposer :机器人处理器类


static class RobotDisposer implements sun.java2d.DisposerRecord {

       private final RobotPeer peer;

       public RobotDisposer(RobotPeer peer) {

           this.peer = peer;

       }

       public void dispose() {

           if (peer != null) {

               peer.dispose();

           }

       }

   }

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

8.mouseMove:鼠标移动方法(线程安全),其中x,y为当前设备像素点


public synchronized void mouseMove(int x, int y) {

       peer.mouseMove(x, y);

       afterEvent();

   }

1.

2.

3.

4.

9:mousePress:鼠标按下事件,传入的参数buttons,为鼠标哪一个键,其常用参数如下


InputEvent.BUTTON1_MASK:鼠标左键


InputEvent.BUTTON2_MASK:鼠标滚轮


InputEvent.BUTTON3_MASK:鼠标右键


public synchronized void mousePress(int buttons) {

       checkButtonsArgument(buttons);

       peer.mousePress(buttons);

       afterEvent();

   }

1.

2.

3.

4.

5.

10:mouseRelease:鼠标弹起事件,传入的参数和mousePress类似,此方法一般和mousePress联合使用,按下鼠标的同时也会弹起鼠标。


checkButtonsArgument:检查按钮的标志组合

peer.mouseRelease(buttons):调用window底层,在当前屏幕将buttons按钮弹起

afterEvent:生成事件后调用,见下文

public synchronized void mouseRelease(int buttons) {

       checkButtonsArgument(buttons);

       peer.mouseRelease(buttons);

       afterEvent();

   }

1.

2.

3.

4.

5.

11.checkButtonsArgument:检查按钮参数


private void checkButtonsArgument(int buttons) {

       if ( (buttons|LEGAL_BUTTON_MASK) != LEGAL_BUTTON_MASK ) {

           throw new IllegalArgumentException("Invalid combination of button flags");

       }

   }

1.

2.

3.

4.

5.

12.mouseWheel:鼠标滚动事件,wheelAmt为鼠标滚动的刻度,如果wheelAmt大于0则向上滚动,如果小于0则向下滚动,例如向上滚动一个刻度,则robot.mouseWheel(1)


public synchronized void mouseWheel(int wheelAmt) {

       peer.mouseWheel(wheelAmt);

       afterEvent();

   }

1.

2.

3.

4.

13.keyPress:按钮按下事件(此类所有int入参都是ASCII进制码)


public synchronized void keyPress(int keycode) {

       checkKeycodeArgument(keycode);

       peer.keyPress(keycode);

       afterEvent();

   }

1.

2.

3.

4.

5.

14.keyRelease:按钮弹起事件


public synchronized void keyRelease(int keycode) {

       checkKeycodeArgument(keycode);

       peer.keyRelease(keycode);

       afterEvent();

   }

1.

2.

3.

4.

5.

15.checkKeycodeArgument:检测按钮是否定义


private void checkKeycodeArgument(int keycode) {

       if (keycode == KeyEvent.VK_UNDEFINED) {

           throw new IllegalArgumentException("Invalid key code");

       }

   }

1.

2.

3.

4.

5.

16.getPixelColor:返回给定坐标屏幕的颜色


public synchronized Color getPixelColor(int x, int y) {

       Color color = new Color(peer.getRGBPixel(x, y));

       return color;

   }

1.

2.

3.

4.

17.创建包含从屏幕读取的像素的图像。这张照片确实如此不包括鼠标光标


@param screenRect 要在屏幕坐标中捕获,


checkScreenCaptureAllowed:检测当前设备是否被允许读取屏幕像素:不能则会抛出异常


checkValidRect:检测screeRect宽度和高度,如果screeRect宽度和高度小于等于0,则抛出IllegalArgumentException


后半部分为读取图像


public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {

       checkScreenCaptureAllowed();


       checkValidRect(screenRect);


       BufferedImage image;

       DataBufferInt buffer;

       WritableRaster raster;


       if (screenCapCM == null) {

           /*

            * Fix for 4285201

            * Create a DirectColorModel equivalent to the default RGB ColorModel,

            * except with no Alpha component.

            */


           screenCapCM = new DirectColorModel(24,

                                              /* red mask */    0x00FF0000,

                                              /* green mask */  0x0000FF00,

                                              /* blue mask */   0x000000FF);

       }


       // need to sync the toolkit prior to grabbing the pixels since in some

       // cases rendering to the screen may be delayed

       Toolkit.getDefaultToolkit().sync();


       int pixels[];

       int[] bandmasks = new int[3];


       pixels = peer.getRGBPixels(screenRect);

       buffer = new DataBufferInt(pixels, pixels.length);


       bandmasks[0] = screenCapCM.getRedMask();

       bandmasks[1] = screenCapCM.getGreenMask();

       bandmasks[2] = screenCapCM.getBlueMask();


       raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);

       SunWritableRaster.makeTrackable(buffer);


       image = new BufferedImage(screenCapCM, raster, false, null);


       return image;

   }

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

25.

26.

27.

28.

29.

30.

31.

32.

33.

34.

35.

36.

37.

38.

39.

40.

41.

42.

43.

18.checkValidRect:检查坐标


private static void checkValidRect(Rectangle rect) {

       if (rect.width <= 0 || rect.height <= 0) {

           throw new IllegalArgumentException("Rectangle width and height must be > 0");

       }

   }

1.

2.

3.

4.

5.

19.checkScreenCaptureAllowed:检查读取像素权限


private static void checkScreenCaptureAllowed() {

       SecurityManager security = System.getSecurityManager();

       if (security != null) {

           security.checkPermission(

               SecurityConstants.AWT.READ_DISPLAY_PIXELS_PERMISSION);

       }

   }

1.

2.

3.

4.

5.

6.

7.

20.afterEvent:事件后调用函数,此方法为内部方法


private void afterEvent() {

       autoWaitForIdle();

       autoDelay();

   }

1.

2.

3.

4.

21.参数isAutoWaitForIdle的set和get方法


public synchronized boolean isAutoWaitForIdle() {

       return isAutoWaitForIdle;

   }

   public synchronized void setAutoWaitForIdle(boolean isOn) {

       isAutoWaitForIdle = isOn;

   }

1.

2.

3.

4.

5.

6.

21.autoWaitForIdle:判定是否自动调用


private void autoWaitForIdle() {

   if (isAutoWaitForIdle) {

       waitForIdle();

   }

}

1.

2.

3.

4.

5.

22.此方法为autoDelay的set和get方法,如果你是用robot编写按键脚本,建议每次调用事件aotoDelay设置为一个随机数,防止被服务器检测出来


public synchronized int getAutoDelay() {

       return autoDelay;

   }

public synchronized void setAutoDelay(int ms) {

       checkDelayArgument(ms);

       autoDelay = ms;

   }

1.

2.

3.

4.

5.

6.

7.

23.delay:主线程休眠,其中ms为多少毫秒


public synchronized void delay(int ms) {

       checkDelayArgument(ms);

       try {

           Thread.sleep(ms);

       } catch(InterruptedException ite) {

           ite.printStackTrace();

       }

   }

1.

2.

3.

4.

5.

6.

7.

8.

24.checkDelayArgument:延迟参数检测方法,该参数必须大于0且小于60s


private void checkDelayArgument(int ms) {

       if (ms < 0 || ms > MAX_DELAY) {

           throw new IllegalArgumentException("Delay must be to 0 to 60,000ms");

       }

   }

1.

2.

3.

4.

5.

25:waitForIdle:等待事件队列中当前所有事件处理完毕


public synchronized void waitForIdle() {

       checkNotDispatchThread();

       // post a dummy event to the queue so we know when

       // all the events before it have been processed

       try {

           SunToolkit.flushPendingEvents();

           EventQueue.invokeAndWait( new Runnable() {

                                           public void run() {

                                               // dummy implementation

                                           }

                                       } );

       } catch(InterruptedException ite) {

           System.err.println("Robot.waitForIdle, non-fatal exception caught:");

           ite.printStackTrace();

       } catch(InvocationTargetException ine) {

           System.err.println("Robot.waitForIdle, non-fatal exception caught:");

           ine.printStackTrace();

       }

   }

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

26.checkNotDispatchThread:检测还未分派的线程,如果队里中存在,将抛出异常,Cannot call method from the event dispatcher thread(无法从事件调度程序线程调用方法)


复制  

private void checkNotDispatchThread() {

       if (EventQueue.isDispatchThread()) {

           throw new IllegalThreadStateException("Cannot call method from the event dispatcher thread");

       }

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
tjCN0TA76tF8
作者其他文章 更多