为AWT的机器人创建DSL

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Win7下硬盘安装Redhat双系统

Win7下硬盘安装Redhat Linux 形成双系统过程详解 需要软件 EasyBCD2.0 和 linux ISO 系统镜像 RedHat linux下载地址&#xff1a;http://www.linuxidc.com/Linux/2013-01/78017.htm 安装前准备工作: 1 一个 Windows 盘 D E F 任选其一都可以&#xff0c;将其格式化为FAT32 格式…

java rmi漏洞工具_学生会私房菜【20200924】Weblogic WLS核心组件反序列化命令执行突破(CVE20182628)漏洞复现...

学生会私房菜学生会私房菜是通过学生会信箱收集同学们的来稿&#xff0c;挑选其中的优质文档&#xff0c;不定期进行文档推送的主题。本期文档内容为&#xff1a;Weblogic WLS核心组件反序列化命令执行突破(CVE-2018-2628)漏洞复现》作者介绍&#xff1a;ChowChow&#xff0c;一…

Java泛型中的多态

从作为Java程序员的早期开始&#xff0c;我们都知道如何实例化和使用Collection对象。 实例化为具体类的List接口将如下所示。 List myArrayList new ArrayList();如果myArrayList应该仅保存Integer对象&#xff0c;则从Java 5编译器开始&#xff0c;按照Java Generics规范…

ASP.NET伪静态-无法读取配置文件,因为它超过了最大文件大小的解决办法

一直都在使用微软URLRewriter&#xff0c;具体的使用方法我就不多说了&#xff0c;网上文章很多。 但最近遇到一个问题&#xff0c;就是当web.config文件里面设置伪静态规则过多&#xff0c;大于2M的时候&#xff0c;就报错&#xff1a;无法读取配置文件&#xff0c;因为它超过…

java定义list_我的Java Web之路59 - Java中的泛型

本系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考&#xff0c;希望能帮助更多(Java)码农和想成为(Java)码农的人。目录介绍再谈Java中的类型为什么需要泛型&#xff1f;Java中的泛型泛型类型泛型方法总结介绍还记得我在这篇文章(我的Java Web之路3…

Spring查找方法示例

当一个bean依赖于另一个bean时&#xff0c;我们使用setter属性或通过构造函数注入bean。 getter方法将向我们返回已设置的引用&#xff0c;但是假设您每次调用getter方法时都想要一个依赖bean的新实例&#xff0c;那么您可能将不得不采用另一种方法。 在本文中&#xff0c;我…

mysql判断数字的函数_Mysql必读MySql判断汉字、日期、数字的具体函数

《Mysql必读MySql判断汉字、日期、数字的具体函数》要点&#xff1a;本文介绍了Mysql必读MySql判断汉字、日期、数字的具体函数&#xff0c;希望对您有用。如果有疑问&#xff0c;可以联系我们。MYSQL学习几个平常用的mysql函数,MySql判断汉字、日期、数字的具体函数分享给大家…

编码:可视化位图

在过去的一个月左右的时间里&#xff0c;我每天花费一些时间来阅读Neo4j代码库的新部分&#xff0c;以使其更加熟悉&#xff0c;而我最喜欢的类之一是Bits类&#xff0c;该类可以完成所有底层工作&#xff0c;并且到磁盘。 特别是&#xff0c;我喜欢它的toString方法&#xff…

通过更改透明度使图片为透明

使用AlphaBlend函数 函数功能 该函数用来显示具有指定透明度的图像。函数原型 AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int hHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunc…

(转)CocoaPods:管理Objective-c 程序中各种第三方开源库关联

在我们的iOS程序中&#xff0c;经常会用到多个第三方的开源库&#xff0c;通常做法是去下载最新版本的开源库&#xff0c;然后拖拽到工程中。 但是&#xff0c;第三方开源库的数量一旦比较多&#xff0c;版本的管理就非常的麻烦。有没有什么办法可以简化对第三方库的管理呢&…

为什么子进程每次执行顺序不一样_看完这篇还不懂Redis的RDB持久化,你来打我...

推荐观看&#xff1a;Redis缓存穿透的终极解决方案&#xff0c;手写布隆过滤器_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.comP8架构师串讲&#xff1a;Redis&#xff0c;zookeeper&#xff0c;kafka&#xff0c;Nginx等技术_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​w…

Spring XD用于数据提取

Spring XD是一个功能强大的工具&#xff0c;它是一组可安装的Spring Boot服务&#xff0c;可以独立运行&#xff0c;在YARN或EC2之上运行。 Spring XD还包括一个管理UI网站和一个用于作业和流管理的命令行工具。 Spring XD是一组功能强大的服务&#xff0c;可与各种数据源一起使…

JDK 9 REPL:入门

会议是聚会Java名人的好地方。 Devoxx France是与Java语言架构师&#xff0c;前同事和老朋友Brian Goetz&#xff08; briangoetz &#xff09;见面的一个机会。 我们谈论了JDK 9&#xff0c;而他全都热衷于REPL。 他提到&#xff0c;尽管Java SE 9中有很多重要功能 &#xff0…

sinaapp mysql连接_手把手教你在新浪云上免费部署自己的网站--连接数据库

看完之后&#xff0c;默认你知道怎么将代码上传到新浪云SAE&#xff0c;并且能够成功运行&#xff0c;连接数据库之前&#xff0c;你必须先创建有一个应用。现在我创建一个名称为sampleone的应用&#xff0c;如下图点击左侧的代码管理&#xff0c;选在右侧创建一个版本然后就会…

HDU-4527 小明系列故事——玩转十滴水 模拟

题意&#xff1a;就是平时玩的十滴水游戏&#xff0c;游戏者拥有一定的水滴&#xff0c;能够滴在某些位置&#xff0c;如果一个点上的体积超过了4就会爆炸&#xff0c;向四周传递一个小水滴。该题就是要求模拟这个过程。 分析&#xff1a;这里有一个问题就是不能够使用递归来处…

win8改win7 教程

新入手的WIN8怎么改成WIN7呢&#xff1f;下面以戴尔Dell V3560 win8换win7系统为例说明&#xff1a; win8改win7本文转自http://jingyan.baidu.com/article/ed2a5d1f2a97ee09f6be17e2.html 第一步&#xff1a;开机过程中不断按F2进入到BIOS&#xff0c;更改bios设置&#xff0c…

7 centos 查看程序文件数量_解析CentOS 7中系统文件与目录管理

LINUXLinux操作系统解析CentOS 7中系统文件与目录管理Linux目录结构Linux目录结构是树形的目录结构根目录所有分区、目录、文件等的位置起点整个树形目录结构中&#xff0c;使用独立的一个“/”表示常见的子目录目录目录名称目录目录名称/root管理员家目录/bin所有用户可执行命…

IE浏览器模式设置

文件兼容性用于定义让IE如何编译你的网页。此文件解释文件兼容性&#xff0c;如何指定你网站的文件兼容性模式以及如何判断一个网页该使用的文件模式。 前言 为了帮助确保你的网页在所有未来的IE版本都有一致的外观&#xff0c;IE8引入了文件兼容性。在IE6中引入一个增设的兼容…

mysql存储过程套嵌_mysql存储过程套嵌

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

拆卸invokedynamic

许多Java开发人员认为JDK的第七版有些令人失望。 从表面上看&#xff0c;仅少数语言和库扩展使它成为了发行版&#xff0c;即Project Coin和NIO2 。 但在幕后&#xff0c;该平台的第七个版本对JVM类型系统进行了最大的扩展&#xff0c;这是它最初发布后引入的。 添加invokedyna…