pywinauto:Windows桌面应用自动化测试(八)

前言

上一篇文章地址:

pywinauto:Windows桌面应用自动化测试(七)-CSDN博客

下一篇文章地址:

暂无

一、实战常用方法

1、批量筛选元素

如果元素的一些属性具备部分相分,那该如何批量获取这些元素呢?如图,假设我想设置IP地址等信息,而每个输入都有一部分相同的情况,当我一键匹配后会有部分输入为空,我将判断为空时输入数值1,该如何做呢?

假设元素的auto_id包含

"FormNetworkAdapterConfigure.frame_2.groupBoxStaticIp.frame_5" 字符串,将该字符串赋值给
auto_id_prefix这个变量,那么我们可以通过方法
descendants()获取所有元素,再再这些元素中筛选出指定元素,并操作这些元素。
    def add_ip_to_auto_match(self):
        '''补充一键匹配的ip'''
        ip_set_window = self._connect_ip_set()
        # 过滤包含指定 auto_id 前缀的子窗口
        all_windows = ip_set_window.descendants()
        auto_id_prefix = "FormNetworkAdapterConfigure.frame_2.groupBoxStaticIp.frame_5"
        matching_windows = [window for window in all_windows if window.automation_id().startswith(auto_id_prefix)]
        # # 输出匹配的窗口信息
        # for window in matching_windows:
        #     print(
        #         f"Title: {window.window_text()}, Auto ID: {window.automation_id()}, Control Type: {window._control_types}")
        # 输出匹配的元素
        StaticIp_list = []
        for window in matching_windows:
            if auto_id_prefix in window.automation_id() and "frameIP.txtIP" in window.automation_id():
                print(window.automation_id())
                StaticIp_list.append(window.automation_id())
        # 为空时输入数字1
        for StaticIp in StaticIp_list:
            wt = ip_set_window.child_window(auto_id=StaticIp).window_text()
            if wt == "":
                ip_set_window.child_window(auto_id=StaticIp).set_text(1)
            print(wt)

这个示例代码中,我们首先使用 descendants 获取所有子窗口,然后使用 Python 的列表解析来过滤出 auto_idFormNetworkAdapterConfigure.frame_2.groupBoxStaticIp.frame_5 开头的所有窗口。这样可以确保获取到所有符合条件的窗口。

(1)代码的功能描述
该方法通过 _connect_ip_set 连接到一个特定的窗口 ip_set_window。
使用 descendants 方法获取所有子窗口,并根据 auto_id 过滤出特定的窗口。
将符合条件的窗口的 automation_id 存储到 StaticIp_list 列表中。
遍历 StaticIp_list,检查每个窗口的文本是否为空,如果为空,则设置为 1,并打印窗口文本。
(2)关键方法解释
descendants(): 获取窗口的所有子窗口。
automation_id(): 获取窗口的自动化 ID。
child_window(auto_id=...): 根据自动化 ID 查找子窗口。
window_text(): 获取窗口的文本。
set_text(): 设置窗口的文本。

2、使用child_window有多个对象符合

此时可以通过上述的descendants()来替换。

假设 list_items = combo_box.child_window(control_type="ListItem") 获取到了三个对象,那么就给出报错信息:

pywinauto.findwindows.ElementAmbiguousError: There are 3 elements that match the criteria {'control_type': 'ListItem', 'top_level_only': False, 'parent': <uia_element_info.UIAElementInfo - '', NetworkAdapterComboBox, None>, 'backend': 'uia'}
此时,可以通过参数found_index指定某个元素,但要获取三个元素时,可以通过descendants()来替换:

        # 获取 ComboBox 中所有的 ListItem 对象
        list_items = combo_box.descendants(control_type="ListItem")
        # 打印每个 ListItem 的信息
        for item in list_items:
            print(item.window_text())
        # 也可以访问每个 ListItem 的其他属性或方法
        # 例如,选择每个 ListItem
        for item in list_items:
            item.select()
            print(f"Selected: {item.window_text()}")

3、下拉选择框的操作方式

item.select()pywinauto 库中的方法,用于选择一个 ListItem 对象。它的作用是模拟用户点击该项,以将其选中。在用户界面中,这相当于在下拉列表中点击某一项来选择它。

在上个例子中,我们调用了item.select()方法去选择元素,通常也会触发点击事件来选中该项,但也有例外。此时,就需要点击才能被选中。

4、子窗口界面遮住父窗口时能连父窗口么

当使用 pywinauto 进行自动化测试时,如果子窗口(如对话框)遮住了父窗口,通常仍然可以与父窗口进行交互。pywinauto 基于控件树和窗口句柄的方式来操作窗口和控件,因此它并不完全依赖于窗口的视觉呈现(即使窗口被遮挡,仍然可以通过它的句柄进行操作)。

5、列表对象的操作方式

列表对象的操作跟表格对象的操作有点相似,但有必要说明一下:

(1)列表对象(List Object)
用途: 列表对象通常用于显示单列数据项的集合,每个数据项通常是一行文本或一个简单的项。列表对象更像是一个一维的数据容器。

常见控件: `ListBox`, `ListView`。
  
结构: 列表对象的每个项(`ListItem`)通常只包含一个文本字段,所有的项都排列在一个垂直或水平方向上。

操作:
  - 可以选择、双击、右键点击、获取文本等操作。
  - 通过 `children()` 获取所有列表项,通常是 `ListItemWrapper` 对象的集合。

示例:
  list_control = window.child_window(control_type="List")
  list_items = list_control.children(control_type="ListItem")

使用场景: 用于简单的数据展示,比如菜单项列表、文件列表等。

(2)表格对象(Table Object)
用途: 表格对象用于显示多列数据项的集合,每个数据项通常是一个二维的数据表格,包括多行和多列。表格对象更像是一个二维的数据容器。

常见控件: `DataGrid`, `Table`, `ListView`(在具有多列时,也可以作为表格处理)。

结构: 表格对象的每一行(`Row` 或 `TableItem`)由多个列组成,每列可以包含不同类型的数据(文本、图像、复选框等)。

操作:
  - 可以选择特定单元格、双击单元格、获取单元格内容、排序列等。
  - 通过 `children()` 或者 `item_by()` 获取表格行或单元格,通常是 `TableItemWrapper` 或 `TableCellWrapper` 对象。

示例:
  table_control = window.child_window(control_type="Table")
  rows = table_control.children(control_type="DataItem")  # 每一行作为一个 DataItem
  cell = table_control.cell(row=0, column=1)  # 获取特定单元格

使用场景: 用于复杂的数据展示,比如电子表格、数据库结果显示、用户表格数据输入等。

主要区别:
数据结构: 列表对象是一维数据结构,表格对象是二维数据结构。
显示形式: 列表对象通常以单列形式展示,表格对象以多列形式展示。
操作复杂性: 表格对象的操作更为复杂,因为需要处理多列、多行数据,而列表对象则只需处理单列数据。
 

(3)简单用法

假设列表元素为list_items ,以下函数实现了依次点击找到的列表元素:

    def click_scheme(self):
        list_items = self.scheme_win.child_window(auto_id="MainForm.widget_client.viScanner.qt_tabwidget_stackedwidget.Equipment.ProjectManagePage.widget_content.listWidget_items", control_type="List").children(control_type="ListItem")
        for item in list_items:
            item.click_input()

(4)列表中内嵌的信息是否可以获取

很遗憾,不行。但是可以通过OCR的方式间接获取,这就涉及到保存图片,可以通过capture_as_image()方法获取列表元素的图片,再对图片进行分析。

                from PIL import ImageGrab, Image
                # 另一种方法
                # rect = item.rectangle()
                # image = ImageGrab.grab(bbox=(rect.left, rect.top, rect.right, rect.bottom))
                # 常用方法
                image = item.capture_as_image()
                # image.show()  # 显示截图
                image.save("element_screenshot.png")  # 保存截图

个人在使用的OCR给大家推荐一下:

pip install paddleocr
pip install paddlepaddle

PaddlePaddle 是由百度开发的一个端到端的开源深度学习平台,类似于 TensorFlow 或 PyTorch。

PaddleOCR 是基于 PaddlePaddle 的一个光学字符识别(OCR)库,专注于文本检测、文本识别和表格识别等任务。

换句话说,PaddleOCR 是构建在 PaddlePaddle 框架之上的一个应用库,利用 PaddlePaddle 提供的底层深度学习能力,专门处理 OCR 任务。

OCR用法:

from paddleocr import PaddleOCR, draw_ocr
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
img_path = r"D:\软件\传统安装\python\mystudy\pages\element_screenshot.png"
result = ocr.ocr(img_path, cls=True)
for block in result:
    for line in block:
        text = line[1][0]  # 提取文本内容
        print(text)

有时候空格会被忽略,这个好像也不是什么大事,咋们也直接忽略就好。如果要识别O空格,可以查阅一些资料,比如下面的链接:

英文内容识别中,空格的识别率较低 · Issue #42 · hiroi-sora/Umi-OCR · GitHub

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion King

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值