Java SDK附带了java.awt.Robot类,该类允许键盘和鼠标输入的自动化以及屏幕捕获的创建。 如果您想编写一个模拟用户输入的小型测试应用程序,或者只想自动化一些重复文本的输入,则此功能非常有用。 但是您不想每次都编写一个完整的Java应用程序。

另一方面,ANTLR是解析器生成器,使我们能够创建“域特定语言”(DSL)。 借助ANTLR,我们可以开发一个简单的DSL,它为java.awt.Robot每种方法提供一个命令。 从那时起,我们可以轻松地为各种简单的自动化任务编写脚本。

第一步是发明新的“ DSL”的语法:

  • 不同的“陈述”应以分号分隔。
  • 每个语句应包含一个“命令”和该命令的几个参数。
  • 注释应该跨越多行(使用类似C的注释/ *…* /,或者仅直到行尾为止。

一个简单的文件可能如下所示:

/*
* A simple example demonstrating the basic features.
*/
delay 300; // sleep for 300ms
mouseMove 20,30;
createScreenCapture 100,100,200,200 file=/home/siom/capture.png;
mouseClick button1;
keyboardInput "Test";
delay 400;

有了这些要求,我们就可以开始写下语法了:

grammar Robot;instructions:(instruction ';')+EOF;instruction:instructionDelay |instructionMouseMove |instructionCreateScreenCapture |instructionMouseClick |instructionKeyboardInput;

我们将语法命名为“机器人”,并定义第一条规则instructions ,以便我们拥有一个或多个指令,后跟一个分号作为指令分隔符,直到到达文件末尾(EOF)。 我们要支持的指令作为规则instruction一部分列出。 不同规则之间的管道表示逻辑或,即仅这些规则之一必须匹配。

最简单的规则是instructionDelay延迟:

instructionDelay:'delay' paramMs=INTEGER;
...
INTEGER:[0-9]+;

该规则以命令“ delay”开头,后跟唯一一个以整数形式指定要休眠的毫秒数的参数。 令牌INTEGER显示在规则下方。 它只是定义了我们希望至少有一个介于0到9之间的数字。 为了简化以后对参数的处理,我们将参数分配给名为paramMs的单独树节点。

进行屏幕截图的规则如下所示:

instructionCreateScreenCapture:'createScreenCapture' x=INTEGER ',' y=INTEGER ',' w=INTEGER ',' h=INTEGER  'file=' file=FILENAME;
...
FILENAME:FileNameChar+;
fragment FileNameChar:[a-zA-Z0-9/\\:_-$~.];

紧随其后的是关键字createScreenCapture ,用户必须在屏幕上应捕获的矩形的左上点提供两个坐标。 接下来的两个坐标表示矩形的宽度和高度。 最后,用户必须提供捕获图像的文件名。

文件名由片段FileNameChar的一个或多个字符组成。 该fragment定义了文件名应允许的所有字符。

使用maven,我们现在可以将此语法存储为src/main/antlr4文件夹中的Robot.g4文件,并利用相应的maven插件生成Java词法分析器和解析器:

<build><plugins><plugin><groupId>org.antlr</groupId><artifactId>antlr4-maven-plugin</artifactId><version>${antlr.version}</version><executions><execution><goals><goal>antlr4</goal></goals></execution></executions></plugin>...</plugins>
</build><dependencies><dependency><groupId>org.antlr</groupId><artifactId>antlr4-runtime</artifactId><version>${antlr.version}</version></dependency>...
</dependencies>

要在我们自己的代码中使用生成的类,必须依赖antlr4-runtime

方法execute()将输入文件的Path作为参数,然后解析并执行它:

public void execute(Path inputPath) throws IOException, AWTException {RobotLexer lexer = new RobotLexer(new ANTLRInputStream(new FileInputStream(inputPath.toFile())));RobotParser parser = new RobotParser(new CommonTokenStream(lexer));final Robot robot = new Robot();parser.addParseListener(new RobotBaseListener() {@Overridepublic void exitInstructionDelay(@NotNull RobotParser.InstructionDelayContext ctx) {int delayParam = Integer.parseInt(ctx.paramMs.getText());LOGGER.info("delay(" + delayParam + ")");robot.delay(delayParam);}...});parser.instructions();
}

该文件的内容通过ANTLRInputStream转发到由ANTLR生成的RobotLexer 。 在词法分析器解析文件并生成令牌流之后,可以将该流传RobotParser实际的RobotParser

为了对传入的指令做出反应,添加了ParseListener 。 幸运的是,ANTLR已经创建了一个基本侦听器,该侦听器使用空的实现来实现所有回调方法。 因此,我们只需要重写我们要处理的方法。 当ANTLR为每个解析器规则创建一个回调方法时,我们可以覆盖例如方法exitInstructionDelay() 。 生成的代码传递的参数的类型为RobotParser.InstructionDelayContex 。 正如我们之前在语法中将参数分配给单独节点一样,此上下文对象具有字段paramMs 。 它的getText()方法以String返回此参数的值。 我们只需要将其转换为整数值,然后将其传递给Robot实例的delay()方法即可。

下面的块中显示了规则instructionCreateScreenCapture的实现:

@Override
public void exitInstructionCreateScreenCapture(@NotNullRobotParser.InstructionCreateScreenCaptureContext ctx) {int x = Integer.parseInt(ctx.x.getText());int y = Integer.parseInt(ctx.y.getText());int w = Integer.parseInt(ctx.w.getText());int h = Integer.parseInt(ctx.h.getText());LOGGER.info("Rectangle rectangle = new Rectangle(" + x + "," + y + "," + w + "," + h + ")");Rectangle rectangle = new Rectangle(x, y, w, h);LOGGER.info("createScreenCapture(rectangle);");BufferedImage bufferedImage = robot.createScreenCapture(rectangle);File output = new File(ctx.file.getText());LOGGER.info("Save file to " + output.getAbsolutePath());try {ImageIO.write(bufferedImage, "png", output);} catch (IOException e) {throw new RuntimeException("Failed to write image file: " + e.getMessage(), e);}
}

其原理与上一条指令所示的相同。 传入的上下文对象的每个参数都有一个字段,这些字符串值必须转换为整数值。 有了这些信息,我们可以构造一个Rectangle对象,调用RobotcreateScreenCapture()方法并存储其BufferedImage

结论

为AWT的机器人创建专用DSL比预期容易。 所提供的maven插件从语法文件中创建所有必需的类,并与之平滑地集成到构建过程中。 生成的DSL可用于自动化简单的鼠标和键盘任务,包括创建屏幕截图。

  • PS:源代码可从github获得 。

翻译自: https://www.javacodegeeks.com/2015/04/creating-a-dsl-for-awts-robot.html

为AWT的机器人创建DSL相关推荐

  1. 为什么awt_为AWT的机器人创建DSL

    为什么awt Java SDK附带了java.awt.Robot类,该类允许键盘和鼠标输入的自动化以及屏幕捕获的创建. 当您要编写一个模拟用户输入的小型测试应用程序时,或者只想自动化一些重复文本的输入 ...

  2. 库卡机器人坐标手势_实操:KUKA机器人创建工具坐标数据

    原标题:实操:KUKA机器人创建工具坐标数据 使用机器人示教器设定工具 图8-8 通过一个固定参考点的工具坐标系的测量分为2步:首先确定工具坐标系的TCP点,然后确定工具坐标系的姿态如表8-7所示. ...

  3. Kotlin创建DSL

    <Kotlin从入门进阶到实战> 什么是DSL DSL(Domain-Specific Language,领域特定语言)指的是专注于特定问题领域的计算机语言.不同于通用的计算机语言,领域特 ...

  4. python对话机器人软件_如何用Python为聊天机器人创建对话?

    我想写一个快速简单的聊天机器人,可以携带与用户的对话.我想知道如何创建对话,允许无限量的输入和响应.现在我使用的代码不允许用户定义输入.这就是我现在正在使用的代码.在# Import the rand ...

  5. 使用Recast.AI创建具有人工智能的聊天机器人

    很多SAP顾问朋友们对于人工智能/机器学习这个话题非常感兴趣,也在不断思考如何将这种新技术和SAP传统产品相结合.Jerry之前的微信公众号文章C4C和微信集成系列教程曾经介绍了Partner如何利用 ...

  6. antlr java_使用ANTLR和Java创建外部DSL

    antlr java 在我以前的文章中,有一段时间我写了关于使用Java的内部DSL的文章. 在Martin Fowler撰写的< 领域特定语言 >一书中,他讨论了另一种称为外部DSL的D ...

  7. martin fowler_用Java和Java 8创建内部DSL,采用Martin Fowler的方法

    martin fowler 目前,我正在阅读Martin Fowler撰写的有关DSL- 特定领域语言的精彩书籍. 围绕DSL的嗡嗡声,围绕轻松支持DSL创建的语言,以及DSL的使用,使我好奇地了解和 ...

  8. 使用ANTLR和Java创建外部DSL

    在以前的一段时间里,我曾写过有关使用Java的内部DSL的文章. 在Martin Fowler撰写的< 领域特定语言 >一书中,他讨论了另一种称为外部DSL的DSL,其中DSL是用另一种语 ...

  9. 用Java和Java 8创建内部DSL,采用Martin Fowler的方法

    目前,我正在阅读Martin Fowler撰写的有关DSL- 特定于域的语言的精彩书籍. 围绕DSL的嗡嗡声,围绕轻松支持DSL创建的语言,以及DSL的使用使我好奇地了解和了解DSL的这一概念. 到目 ...

最新文章

  1. 【解决】联想thinkpad E40 如何禁用触摸板
  2. MongoDB(一):简介
  3. MySQL之事务隔离级别--转载
  4. Duplicate keys detected: '0'. This may cause an update error.
  5. Linux vi/vim基础知识
  6. 曾鸣:未来十年,将确定智能商业的格局|干货
  7. Codeforces Round #701 (Div. 2) E. Move and Swap 思维 + dp
  8. qemu a fast and portable dynamic translator——大致翻译
  9. mysql 密码保存格式_mysql5.6使用老格式密码
  10. 热传导方程的差分解法c语言,九热传导方程的差分解法.PPT
  11. cfa三级真题和mock_cfa三级要看哪些书?
  12. plotly系列 | 绘制散点图组合箱线图(联合图)
  13. Word中删除空白页的4种方法
  14. 集群通信:从心跳说起
  15. 自己动手搭建家庭局域网(二),NAS存储+千兆网
  16. linux编辑框软键盘自动弹出,带输入框的Dialog自动弹出软键盘
  17. 华硕天选2 WLAN不可用解决办法
  18. Ubuntu 16.04下EasyOpenJTAG+OpenOCD的安装和使用【转】
  19. GIS地图基础知识--入门教程
  20. 错题集:HDLBits lfsr5 Galois型lfsr

热门文章

  1. jquery实现单击div切换背景,再次单击回到原来样式
  2. java实现邮件发送准备工作(前期配置)
  3. frameset和frame
  4. python的pandas库中如何计算每列出现最多的值_Python Pandas:计算多个列的每个唯一值的显示次数...
  5. centos7 切换中文输入法 无需安装
  6. python中debug有什么用途_史上最方便的Python Debug工具
  7. think-in-java(9)接口
  8. java oca_OCA第7部分中的Java难题
  9. tf.metrics._将指标标签与MicroProfile Metrics 2.0一起使用
  10. java单例枚举_Java增强枚举的用例