wxPython应用开发-后台线程更新大量数据到wxGrid避免ui无响应

news2024/11/18 0:00:07

一、问题描述

最近几天,我在用python开发一个数据处理的小工具。需要将xls文件中的大量数据(少则几千行多则几万行)读取出来后进行处理。其中一个功能是需要实现将读取到的原始数据和计算出来的结果在软件界面中以表格形式展示出来。

在python应用开发中,我基本用wxFormBuilder进行软件界面的设计,因此用到wxPython的时候很多。wxPython中的表格类是wx.grid。这次开发过程中遇到的问题是,通过pandas将几万行数据从xls文件中读取到dataframe中后,再更新到软件主界面中的wxGrid中时,由于数据很大,导致软件ui在一段时间内无响应,一直到数据全部写入"时点库存表“中后,才会响应。

(从xls文件读取几万行数据后,向wxGrid加载数据时,出现未响应提示)

本软件中将数据从dataframe对象(self.df_kcb)写入到ui上显示为“时点库存表“的wxGrid对象(self.m_grid_kcb)中的关键代码如下:

# self.m_grid_kcb是wxGrid对象,self.df_kcb是dataframe对象
# 在执行下述代码之前,会首先清空self.m_grid_kcb
# 然后根据self.df_kcb中的数据行数修改self.m_grid_kcb行数,使两者保持一致

for x in range(self.grid_kcb_rows):  # self.grid_kcb_rows为表格行数
    for y in range(6):  # 本软件中为时点库存表为6列
        self.m_grid_kcb.SetCellValue(x, y, str(self.df_kcb.iloc[x][y]))  # 逐单元格将数据写入wxGrid中

该代码使用了双循环语句,逐个单元格的写入数据,效率不高,在遇到几万行数据时,就导致了ui无响应了。

二、解决办法

我在网上搜索相应的解决办法,找到了如下的一段话。

————————————————————————————————————————

在Python中,将大量数据写入wxPython的wx.grid.Grid控件可能会导致UI响应变慢。为了提高响应性,可以尝试以下方法:

1.分批写入数据:不要一次性将所有数据都加载到wx.grid.Grid中,而是使用分页或滚动机制,每次只加载可见的数据。

2.使用wx.lib.delayedresult:这个模块可以帮助你在一个单独的线程中处理数据的加载,从而不会阻塞UI线程。

3.避免不必要的更新:只有当数据真正改变时才更新wx.grid.Grid,避免不必要的重绘和布局操作。

————————————————————————————————————————

第一个方法,我在去年开发一款软件的时候已经用过了,那款软件中的dataframe对象内的数据量也是有上万行,采用分页显示,每次只显示当前页的几十行数据,通过导航按钮切换页面,没有出现过未响应的情况。但这次我不准备采用这个方法,因为走重复的路是无法学到新知识的。

第二个方法,在那段话后面确实附带了相关的代码示例,但是我尝试将示例融合到我的代码中,确没有成功,总是出现错误。

第三个方法嘛,则不适合当前的应用场景。因为我的应用每次都会选择加载不同的数据,数据量也不一样,必然会对wxGrid中的所有内容都进行更新。

我仍然坚持在一个页面内显示所有的数据,那么就必须解决ui无响应的问题。再次搜索的时候,我使用了“python 如何实现在后台线程中将大量数据写入wxGrid”的关键字起到了作用,百度AI给了我一个有效的答案。

这个答案中的示例直接进行测试是有效的,在想wxGrid加载数据过程中,ui界面不会出现未响应的情况。

(直接运行后,界面有响应,往下拖可以看到数据还没有更新完)

(拖动滑动条的过程中,可以看到数据在更新)

这个代码的关键是用threading模块创建后台线程,并在线程中使用wxCallAfter方法更新wxGrid。

为了实现后台线程操作,要创建一个类:

class WorkerThread(threading.Thread):
    """ 后台线程向wxGrid加载数据 """
    def __init__(self, grid, df, rows, cols):
        threading.Thread.__init__(self)
        self.grid = grid
        self.df = df
        self.rows = rows
        self.cols = cols

    def run(self):
        for row in range(self.rows):
            for col in range(self.cols):
                wx.CallAfter(self.grid.SetCellValue, row, col, str(self.df.iloc[row][col]))

然后在我的主程序中,将之前的更新wxGrid的双循环语句替换成以下的代码:

self.worker = WorkerThread(self.m_grid_kcb, self.df_kcb, self.grid_kcb_rows, 6)  # 后台线程更新到grid
self.worker.start()

我参照示例修改了自己的软件,让更新wxGrid的操作在后台线程中执行,就解决了ui未响应的问题了。效果如下:

(没有出现未响应的情况,可以拖动滑条到底,表格的行数已更新,但数据还没有更新完)

(数据更新完的情况,在更新过程中,可以拖动滑条查看数据更新情况)

三、百度AI给的答案和代码

我在百度ai搜索到的文字内容和示例代码如下(代码中我添加了一点标注):

在Python中,你可以使用threading模块来创建后台线程,并在该线程中更新wxPython界面中的wxGrid。为了安全地在不同的线程之间更新GUI,你需要使用wxPython提供的wx.CallAfter方法。

以下是一个简单的例子,展示如何在后台线程中将大量数据写入wxGrid:

import wx
import wx.grid
import threading
import time


class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, -1, "wxGrid Example")
        self.grid = wx.grid.Grid(self)

        # 创建并设置表格
        self.grid.CreateGrid(100, 2)  # 100行2列
        self.grid.SetRowLabelSize(-1)
        self.grid.SetColLabelSize(-1)

        # 创建并启动后台线程(这两行代码代替我之前写的双循环语句)
        self.worker = WorkerThread(self.grid)
        self.worker.start()


# 这个类可以直接复制到自己的代码中后根据情况进行修改
class WorkerThread(threading.Thread):
    def __init__(self, grid):
        threading.Thread.__init__(self)
        self.grid = grid

    def run(self):
        # 模拟数据生成(这行代码,实际应用要替换成实际要写入wxGrid中的数据)
        data = [(i, i * 2) for i in range(100)]
        # 将数据写入wxGrid表格中(range方法中的行数和列数,按实际应用修改)
        for row in range(len(data)):
            for col in range(2):
                wx.CallAfter(self.grid.SetCellValue, row, col, str(data[row][col]))
            # 模拟耗时操作(这行代码,在实际应用中要删除)
            time.sleep(0.1)


def main():
    app = wx.App(False)
    frame = MyFrame(None)
    frame.Show(True)
    app.MainLoop()


if __name__ == '__main__':
    main()

在这个例子中,WorkerThread类是一个后台线程,它负责生成和处理数据。在MyFrame类的初始化方法中,创建了一个wx.grid.Grid对象,并启动了WorkerThread

WorkerThreadrun方法中,我们通过双层循环模拟了将数据填充到wxGrid中的过程。每设置完一个单元格的值后,我们使用wx.CallAfter来确保在GUI线程中执行这个更新。这样可以避免在后台线程中直接更新GUI,从而避免潜在的线程安全问题。

请注意,这个例子中的time.sleep(0.1)是模拟耗时操作,实际应用中应该去掉或替换为实际的计算或IO操作。此外,根据实际情况,你可能需要更复杂的同步机制,例如使用事件或其他同步原语来通知主线程更新GUI。

希望以上的内容,对大家有用。

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

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

相关文章

Sectigo证书介绍以及申请流程

Sectigo (原Comodo CA)是全球SSL证书市场占有率最高的CA公司,目前将近40%的SSL证书用户选择了Sectigo。由于其产品安全,价格低,受到大量站长的信任和欢迎。Sectigo旗下的SSL证书品牌包括Sectigo, Positive SSL, Sectigo Enterprise等。 品牌…

卷积常用网络

目录 1.AlexNet2.VGG3.GoogleNet4.ResNet5.MobileNet 1.AlexNet AlexNet是2012年ISLVRC 2012(ImageNet Large Scale Visual Recognition Challenge)竞赛的冠军网络。 首次利用 GPU 进行网络加速训练。使用了 ReLU 激活函数,而不是传统的 Si…

基于 Arm 虚拟硬件的 TinyMaix 超轻量级神经网络推理框架的项目实践

本实验过程中所显示的优惠价格及费用报销等相关信息仅在【Arm AI 开发体验创造营】体验活动过程中有效,逾期无效,请根据实时价格自行购买和体验。同时,感谢本次体验活动 Arm 导师 Liliya 对于本实验手册的共创与指导。 详见活动地址&#xff…

【大比武08】利用RAG技术构建档案智能问答系统

关注我们 - 数字罗塞塔计划 - # 大比武2024 本篇是参加“华夏伟业”杯第二届档案信息化公司业务与技术实力大比武(简称“大比武 2024”)的投稿文章,来自燕山大学档案馆(校史馆)的实际项目,由河北科怡科技…

拍摄的视频内容怎么做成二维码?视频在线转换成二维码的方法

怎么把拍的个人才艺视频做成二维码呢?现在扫码看视频是实现内容快速传播的一种常用方式,所以很多人会将自己拍摄的视频制作二维码图片,然后分享给其他人扫码获取内容,对于内容的传播速度及用户体验有很好的提升,在很多…

NTLM Relay Gat:自动化NTLM中继安全检测工具

关于NTLM Relay Gat NTLM Relay Gat是一款功能强大的NTLM中继威胁检测工具,该工具旨在利用Impacket工具套件中的ntlmrelayx.py脚本在目标环境中实现NTLM中继攻击风险检测,以帮助研究人员确定目标环境是否能够抵御NTLM中继攻击。 功能介绍 1、多线程支持…

【开发利器】使用OpenCV算子工作流高效开发

学习《人工智能应用软件开发》,学会所有OpenCV技能就这么简单! 做真正的OpenCV开发者,从入门到入职,一步到位! OpenCV实验大师Python SDK 基于OpenCV实验大师v1.02版本提供的Python SDK 实现工作流导出与第三方应用集…

Java---Cloneable接口---浅克隆和深克隆

在Java中,我们如何实现一个对象的克隆呢? 在Java中实现对象的克隆,我们要用到Cloneable接口。克隆也分为浅克隆和深克隆。 1.实现浅克隆 1.重写clone方法 当我们想直接通过前面已经建立好的对象来调用Object类中的clone方法时,…

vbs执行报错vbs没有文件拓展,双击无法打开

如果看不到文件扩展名需要设置: 无法双击打开vbs 一般为注册表问题 解决办法 将下方代码保存为xxx.reg Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.VBS] "VBSFile" [HKEY_CLASSES_ROOT.VBS\PersistentHandler] "{5e941d80-bf96-…

VBA让按钮消失

要求 用VBA搞小程序,有个录入数据的按钮,点击后进行录入数据的操作,操作完成后这个按钮就是灰的,点不动,这个怎么做? 实现过程 没找到让按钮变灰的方法,退而求其次,让按钮消失。 …

linux部署运维1——centos7.9离线安装部署web或java项目所需的依赖环境,包括mysql8.0,nginx1.20,redis5.0等工具

在实际项目部署运维过程中,如果是云服务器,基本安装项目所需的依赖环境都是通过yum联网拉取网络资源实现自动化安装的;但是对于一些特殊场合,在没有外部网络的情况下,就无法使用yum命令联网操作,只能通过编…

Kunpeng Pro测评使用报告

1. 概述 前段时间,收到两条CSDN的短信,邀请我参加Kunpeng Pro的测评活动。说起来,自己玩过的开发板已经不在少数,而自己作为半导体行业的从业者,手上开发过的芯片也有十几款,小到Arm Cortex-A53&#xff0…

北美互联网裁员太狠了,程序员“做管理上岸”越来越难

北美互联网现在裁员太狠了,“做管理上岸”这种事情在现在这种行业形势已经基本不存在了,这个人管理40人的团队该裁还是裁。 然而硅谷还是中国程序员心中的圣地(华子一定程度上也是很多人的心之所向,技术大厂捞人,前后…

Excel计算两个日期之间差额天数及DATEDIF使用

一.计算两个日期之间的差额天数 1.两个日期直接相减就可以得到两个日期间隔的天数,这里需要注意日期格式哦 日期格式需要为XXXX/XX/XX,不能为XXXX.XX.XX,否则显示Value错误如下。 二.使用DATEDIF函数计算差额天数 该函数只能手写,好像不能自…

应对意外断电:气膜建筑的安全防护与智能管理—轻空间

气膜建筑以其独特的结构和高效的建设方式,广泛应用于各类场馆、仓储设施和临时展馆。然而,当遇到意外断电导致气膜内部无法送风时,如何避免气膜倒塌,确保建筑安全呢? 断电应急响应 气膜建筑配备了先进的智能控制系统&a…

从GIMPLE到RTL

从GIMPLE到RTL 从GIMPLE到RTLGIMPLE序列测试代码:CFG如下所示: 一些典型数据结构RTL生成的基本过程变量展开计算当前函数堆栈(Stack Frame)的初始状态变量展开的初始化对可以展开的变量进行展开操作,生成该变量对应的R…

day17

第一题 本题可以采用快速排序的思想,适应随机数指定和三指针划分数组为三个区域的思想: 其中指针的移动细节如上题故事,如下所示: 当a区域的商都大于k时,我们要查找的k位置元素就在左区域,我们进一步在左区…

适合源代码的加密系统

在信息化高度发展的今天,源代码的安全问题日益受到重视。源代码是企业或组织的核心资产,一旦泄露或被篡改,将会对其造成巨大的经济损失和声誉风险。因此,如何有效防止源代码的泄露和算改成为了企业和组织急需解决的问题。沙盒技术…

Git时光机、Git标签、Git分支、GitHub协作

Git时光机(切换版本) 1.查看提交历史 HEAD指针指向这次分支的最后一次提交 版本信息一行显示【git log --prettyoneline】 2.引用日志【git reflog】 (只在自己的工作区中存在) 非常重要:当HEAD指针进行切换之后&…

有类似注册表编辑器的vb6源码吗?vba注册表编辑器

第一步是要实现注册表功能的读写,所有数据类型,枚举列出所有子项 第二步,树形控件之类显示,可视化修改,查看 第三步,导入导出注册表 第四步,注册表监控,检测哪些注册表项是新建、删除…