虚拟控件API

虚拟控件的API大致可分为三类:

  1. 基础操作API:与传统控件操作类似的通用方法,用于点击、双击、存在性检查、高亮、鼠标移动、键盘输入、截图等。
  2. 文字识别(OCR)相关API:通过OCR识别虚拟控件中的文字,并可对识别出的文字进行点击操作。
  3. 图像比较API:通过图像比对技术检查虚拟控件当前界面与预期图像是否一致,以实现视觉验证。

类型定义

JavaScript
Python
export interface Virtual {
    // 基础操作
    click(x?: number, y?: number, mousekey?: number): Promise<void>;
    dblClick(x?: number, y?: number, mousekey?: number): Promise<void>;
    exists(seconds: number): Promise<boolean>;
    highlight(duration?: number): Promise<void>;
    moveMouse(x?: number, y?: number, seconds?: number): Promise<void>;
    pressKeys(keys: string, opt?: PressKeysOptions | number): Promise<void>;
    rect(): Promise<Rect>;
    takeScreenshot(filePath?: string): Promise<string>;
    wheel(value: number): Promise<void>;
    modelImage(options?: {encoding: 'buffer' | 'base64'}): Promise<string | Buffer>;
    modelProperties(all?: boolean): {[x: string]: any};
    // OCR相关
    visualText(options?: { whitespace: boolean }): Promise<string>;
    clickVisualText(text: string, options?: {
         cache: boolean, 
         x: number, 
         y: number, 
         button: number, 
         double: boolean, 
         down: boolean, 
         up: boolean }): Promise<void>;
    textitems(): Promise<IQtControl[]>;
    // 图像比较相关
    checkImage(options?: CheckImageCompareOptions | string): Promise<void>;
}
class Virtual:
    def click(x: Optional[int] = None, y: Optional[int] = None, mousekey: Optional[int] = None) -> None
    def dblClick(x: Optional[int] = None, y: Optional[int] = None, mousekey: Optional[int] = None) -> None
    def exists(seconds: int) -> bool
    def highlight(duration: Optional[int] = None) -> None
    def moveMouse(x: Optional[int] = None, y: Optional[int] = None, seconds: Optional[int] = None) -> None
    def pressKeys(keys: str, opt: Union[PressKeysOptions, int] = None) -> None
    def rect() -> Dict[str, int]
    def takeScreenshot(filePath: Optional[str] = None) -> str
    def wheel(value: int) -> None
    def modelImage(options: Optional[Dict[str, str]] = {'encoding': 'base64'}) -> Union[str, bytes]
    def modelProperties(all: Optional[bool] = False) -> Dict[str, Any]
    # OCR相关
    def visualText(options: Dict[str, bool]) -> str
    def clickVisualText(text: str, options: Optional[Dict[str, Union[bool, int]]]) -> None
    def textitems() -> List[QtControl]
    # 图像比较相关
    def checkImage(options: Optional[any]=None) -> None

1. 基础操作API

这些方法的用法与Qt或Windows自动化的通用控件操作类似,可参考:

主要API如下:

  • click / dblClick:点击或双击虚拟控件内指定位置(坐标可选,不传则默认控件中心)。
  • exists(seconds: number):在指定秒数内检查该虚拟控件是否存在。
  • highlight(duration?: number):高亮显示该虚拟控件,辅助调试和定位。
  • moveMouse:将鼠标移动到虚拟控件内某点。
  • pressKeys:在该控件中输入特定按键序列。
  • rect():获取虚拟控件的矩形区域信息。
  • takeScreenshot(filePath?: string):截取虚拟控件当前区域的屏幕图像。
  • wheel(value: number):在虚拟控件区域内滚动鼠标滚轮。

2. OCR相关API

当界面中的文字控件无法直接识别时,可通过OCR从虚拟控件中提取文本,并基于文本进行点击操作。更多OCR原理与详情请参考图像字符识别(OCR)

visualText(options?: {whitespace: boolean})

将虚拟控件区域内的图像进行OCR识别,并返回识别出的文本字符串。

参数:

  • options: (可选)识别选项
    • whitespace:boolean类型,指定是否识别空格,默认为 false

返回值:

  • Promise<string> - 返回图片中的文本内容。

示例代码

JavaScript
Python
let text = await model.getVirtual("Virtual1").visualText();
console.log('识别出的文本:', text);
text = model.getVirtual("Virtual1").visualText()
print('识别出的文本:', text)

clickVisualText(text: string, options?: {cache: boolean, x: number, y: number, button: number, double: boolean, down: boolean, up: boolean})

使用OCR在虚拟控件中查找指定文字,并对该文字区域进行点击。

参数:

  • textstring - 待查找的文字(如“打开”)。
  • options: (可选)object类型,文字点击时的操作选项。
    • cache:boolean 类型,设置是否缓存识别信息,默认为 false。设置为 true 时,将复用上一次OCR结果,从而提高后续在同一控件内点击其他文字的响应速度。
    • x: number 类型,点击位置相对于文字区域左上角的水平偏移量(像素)。0 表示点击文字区域的水平中心位置。默认值为 0
    • y: number 类型,点击位置相对于文字区域左上角的垂直偏移量(像素)。0 表示点击文字区域的垂直中心位置。默认值为 0
    • button: number类型,表示要使用的鼠标按键,1为左键,2为右键,缺省值为1,即默认为左键。详细的键值列表见鼠标键枚举类
    • double: boolean类型,设为true时,在指定目标画布位置双击鼠标按钮,缺省值为false
    • down: boolean类型,在指定目标画布位置按下鼠标按钮(不释放),缺省值为false
    • up: boolean类型,在指定目标画布位置释放鼠标按钮,缺省值为false

返回值:

  • 不返回任何值的异步方法。

示例代码(复用OCR缓存信息)

以下示例演示了如何使用 cache 选项。以 Windows 自带的计算器为例,识别计算器的数字面板,并将其添加到模型中,对象名为 "Number pad"。

JavaScript
Python
(async function () {
   let numPad = model.getGeneric("Number pad").getVirtual();
   await numPad.clickVisualText('4', { cache: true });
   await numPad.clickVisualText('5', { cache: true });
   await numPad.clickVisualText('6', { cache: true });
})();
numPad = model.getGeneric("Number pad").getVirtual()
numPad.clickVisualText('4', { 'cache': True })
numPad.clickVisualText('5', { 'cache': True })
numPad.clickVisualText('6', { 'cache': True })
在此示例中,首次点击数字 "4" 时会进行 OCR 识别并稍作停留。随后点击 "5" 和 "6" 时,由于启用了缓存选项,因此无需再次进行 OCR 识别,操作速度更快。

示例代码(双击虚拟控件中文字的指定位置)

以下示例演示了如何使用xydouble选项。在这个示例中,对象名为virtual的虚拟控件上文字ABC的可视区域将会被定位,随后鼠标将在该可视区域以左上角为原点、水平偏移30个像素点、垂直偏移20个像素点的位置进行双击操作。

JavaScript
Python
model.getVirtual("virtual").clickVisualText("ABC", { x: 30, y: 20, double: true });
model.getVirtual("virtual").clickVisualText("ABC", { 'x': 30, 'y': 20, 'double': True })

示例代码(右键单击虚拟控件中的文字)

以下示例演示了如何使用xybutton选项。在这个示例中,对象名为virtual的虚拟控件上文字XYZ的可视区域将会被定位,随后鼠标将在该可视区域中心位置进行右键单击操作。

JavaScript
Python
model.getVirtual("virtual").clickVisualText("XYZ", { x: 0, y: 0, button: 2 });
model.getVirtual("virtual").clickVisualText("XYZ", { 'x': 0, 'y': 0, 'button': 2 })

异常处理

当在指定控件内未找到给定文字时,将抛出异常。可通过takeScreenshot()截屏和Ocr.getTextLocations()查看识别的文字块信息以进行诊断。

JavaScript
(async function () {
    let numPad = model.getGeneric("Number pad").getVirtual();
    let snapshot = await numPad.takeScreenshot();
    let blocks = await Ocr.getTextLocations(snapshot);
    console.log(JSON.stringify(blocks, null, 2))
})();

textItems()

获取虚拟控件列表,每个控件包含一个可视文本块

  • 返回值:Promise<Control[]>类型,级联虚拟控件内以文本块为单位的子虚拟控件。

示例代码 假设名为virtual1的虚拟控件(如下图)调用textItems()方法,返回值应为一个长度为4的虚拟控件列表,图中的FileEditViewHelp字样将各成为一个虚拟控件。

JavaScript
Python
let items = await model.getVirtual("virtual1").textItems();
// 返回值应为4
console.log(items.length);
items = model.getVirtual("virtual1").textItems()
# 返回值应为4
print(len(items))

3. 图像比较API

通过图像比较技术检查虚拟控件当前画面与预期图像是否一致。可用于视觉验证,如检测控件的状态变化。

checkImage(options?: CheckImageCompareOptions | string)

此方法用于将目标控件的当前渲染图像与一个指定的参考图像进行比对。当检测到实际图像与参考图像之间的差异超出预设的容忍阈值时,方法将抛出错误,并显示图像间的差异部分,从而帮助定位问题。checkImage 是确保用户界面(UI)控件视觉保真度的关键工具。

优先使用虚拟控件自身的截图进行图像比对;如果该控件没有截图,则会从父控件的截图中裁剪对应区域进行比较。

参考图像的指定方式及优先级:

该方法通过 options 参数灵活指定参考图像及比较行为:

  1. 通过 Base64 数据: 如果 options 对象中提供了 image 属性(Base64 编码的字符串或 Node.js Buffer),则以此数据作为参考图像。
  2. 通过文件路径:
    • 如果 options 本身是一个字符串,它将被视为图像文件的路径。
    • 如果 options 是一个对象,且未提供 image 属性但提供了 imagePath 属性,则系统会加载 imagePath 指定的文件作为参考图像。
  3. 通过模型内置快照: 如果 options 参数被省略,或者是一个空对象,或者对象中仅包含比较选项(如 pixelPercentTolerance)而无具体的图像源(imageimagePath),则默认使用模型文件中为该控件预存的参考图像(快照)。

参数详解

  • 类型: CheckImageCompareOptions | string (可选)

  • CheckImageCompareOptions 配置对象: 当 options 参数为一个对象时,您可以配置以下属性来指定参考图像源并调整比较的精度和行为:

    • 图像源指定:

      • image?: string | Buffer: (可选) 提供 Base64 编码的图像数据(string 类型)或 Node.js 的 Buffer 对象。如果提供此参数,控件的当前图像将与此图像数据进行比较。
        • 注意: 在 Python 环境中,仅支持传递 Base64 编码的字符串。
      • imagePath?: string: (可选) 提供图像文件的路径字符串。如果未提供 image 属性,但提供了此属性,则系统会加载并使用此路径指定的图像文件作为参考。
    • 图像比较选项:

      • colorTolerance?: number: (可选) number 类型,定义了在颜色匹配时允许的最大差异容忍度。默认值为 0.1。数值越小,颜色匹配越严格。
      • pixelPercentTolerance?: number: (可选) number 类型,定义了允许的最大像素百分比差异容忍度。例如,默认值 1 表示最多允许 1% 的像素差异。
      • pixelNumberTolerance?: number: (可选) number 类型,定义了允许的像素数量差异容忍度。如果设置为 0,则表示在像素数量上不允许任何差异(除非被 pixelPercentTolerance 覆盖)。
      • ignoreExtraPart?: boolean: (可选) boolean 类型,用于指定在比较时是否忽略其中一张图像多出来的部分。默认为 false

返回值:

  • Promise<void>: 不返回任何值的异步方法。如果图像比较失败,则会抛出错误。

使用示例

以下示例展示了 checkImage 方法的多种用法,假设 model.getVirtual("button_image") 返回一个虚拟控件对象:

JavaScript
Python
// 示例准备:获取图像的 Base64 编码 (仅为演示,实际使用时按需获取)
let expect_image = await Image.fromFile("button1.png");
let image_data_base64 = await expect_image.getData({encoding: 'base64'});

// 1. 与 Base64 图像比较
await model.getVirtual("button_image").checkImage({ image: image_data_base64 });

// 2. 与 Base64 图像比较,并自定义容忍度
await model.getVirtual("button_image").checkImage({ image: image_data_base64, pixelPercentTolerance: 10 });

// 3. 与文件路径图像比较 (直接传递路径字符串)
await model.getVirtual("button_image").checkImage("button1.png");

// 4. 与文件路径图像比较 (通过 options.imagePath)
await model.getVirtual("button_image").checkImage({ imagePath: "button1.png" });

// 5. 与文件路径图像比较,并自定义容忍度
await model.getVirtual("button_image").checkImage({ imagePath: "button1-error.png", pixelPercentTolerance: 5, colorTolerance: 0.05 });

// 6. 与模型内置快照比较,并自定义容忍度
await model.getVirtual("button_image").checkImage({ pixelPercentTolerance: 0.5, colorTolerance: 0.05 });

// 7. 与模型内置快照比较 (使用默认容忍度)
await model.getVirtual("button_image").checkImage();
import base64 # Python 示例需要导入 base64 模块

# 示例准备:获取图像的 Base64 编码
base64_value = None
with open("button1.png", "rb") as f:
    base64_value = base64.b64encode(f.read()).decode("utf-8")

# 1. 与 Base64 图像比较
model.getVirtual("button_image").checkImage({ 'image': base64_value })

# 2. 与 Base64 图像比较,并自定义容忍度
model.getVirtual("button_image").checkImage({ 'image': base64_value, 'pixelPercentTolerance': 10 })

# 3. 与文件路径图像比较 (直接传递路径字符串)
model.getVirtual("button_image").checkImage("button1.png")

# 4. 与文件路径图像比较 (通过 options['imagePath'])
model.getVirtual("button_image").checkImage({ 'imagePath': "button1.png" })

# 5. 与文件路径图像比较,并自定义容忍度
model.getVirtual("button_image").checkImage({ 'imagePath': "button1-error.png", 'pixelPercentTolerance': 5, 'colorTolerance': 0.05 })

# 6. 与模型内置快照比较,并自定义容忍度
model.getVirtual("button_image").checkImage({ 'pixelPercentTolerance': 0.5, 'colorTolerance': 0.05 })

# 7. 与模型内置快照比较 (使用默认容忍度)
model.getVirtual("button_image").checkImage()

在上述示例中,若 button_image 控件的当前视觉表现与指定的参考图像(无论是 Base64 数据、文件,还是内部快照)的差异超出了设定的容忍度(例如 colorTolerancepixelPercentTolerance),checkImage 方法将抛出错误,指示测试失败。

results matching ""

    No results matching ""