PyQt5 界面显示无响应的实现

 更新时间:2020年03月26日 14:17:56   作者:zulien  
这篇文章主要介绍了PyQt5 界面显示无响应的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在GUI程序中,主线程也叫GUI线程,因为它是唯一被允许执行GUI相关操作的线程。对于一些耗时的操作,如果放在主线程中,就是出现界面无法响应的问题。

界面假死分析

在编写QT的界面程序时,当我们调用QApplication.exec()时,我们就启动了QT的事件循环。在开始的时候,QT会发出一些事件来显示和绘制窗口部件。在这之后,事件循环就开始运行,不断地检查是不是有事件发生并且把这些事件发送给应用程序中的QObject。

当一个事件被处理时,其他事件也可能会产生并且追加到QT的事件队列中。如果我们在处理一个特定的事件上耗费过多的时间,用户界面就会变得不能够响应。例如在OCS保存一个观测流程的过程中,一直到文件保存完毕,窗口系统产生的一些事件才会被处
理。在保存过程中,这个应用程序就不能响应窗口系统的请求来重绘自己。

解决方法

  • 方式一使用多线程:一个处理应用程序用户界面的线程,另外一个执行文件保存的线程。
  • 方法二:调用QApplication.processEvents()

博主推荐使用第二种方法,该方法是在事件处理程序中调用QApplication.processEvents()。

这个函数告诉QT处理来处理任何没有被处理的事件,并且将控制权返回给调用者。实际上,QApplication.exec()就是一个不停调用QApplication.processEvents()函数的小while循环。这种方式的危险性在于,也许用户在观测流程未保存好之前就关闭了主窗口,或者在界面上通过鼠标或键盘执行了其它的输入,以至于观测流程未保存好就企图被程序使用。对于这个问题的解决办法是把 qApp -> processEvents(); 替换为 qApp -> eventLoop() -> processEvents( QEventLoop::ExcludeUserInput ); 通过这个调用告诉QT忽略鼠标和键盘事件。

 ...
  def downfile(self,file, url):
  print("开始下载:", file, url)
  try:
   r = requests.get(url, stream=True)
   with open(file, 'wb') as fd:
    for chunk in r.iter_content():
     fd.write(chunk)
     QApplication.processEvents()
  except Exception as e:
   print("下载失败了", e)
 ...

------------------------------------------补充一下方法一--------------------------》》》》》

说实话快有大半年没怎么使用过python了,关于多线程的处理方式,解释可能不是那么清楚。(目前是一个phper,上半年基本是补PHP方面的基础知识,也就是够用还不精通的一个状态)

先上一个半年前的小作品,是关于微信公众号方面的一些。

这里就不谈用途与使用方法了,大概的讲一下,遇到界面假死的处理方法之一。话不多说,先上代码

from PyQt5.QtCore import QThread, pyqtSignal
 
class interface(QMainWindow, Ui_MainWindow):
 """
 Class documentation goes here.
 """
 def xxxx():
  "此处省略无数行代码......"
  self.Work()
 
 def Work(self):
  self.thread = RunThread()
  self.thread.start()
 
class RunThread(QThread):
 # python3,pyqt5与之前的版本有些不一样
 # 通过类成员对象定义信号对象
 # _signal = pyqtSignal(str)
 
 trigger = pyqtSignal()
 
 def __init__(self, parent=None):
  super(RunThread, self).__init__()
 
 def __del__(self):
  self.wait()
 
 def run(self):
  # 处理你要做的业务逻辑,这里是通过一个回调来处理数据,这里的逻辑处理写自己的方法
  dlg.Config['user'] = dlg.check_account['account']
  dlg.Config['passwd'] = dlg.check_account['password']
  dlg.Config['jk'] = 'http://xxx.com'
  if dlg.num != 1:
   dlg.operato.config_item(dlg.Config, dlg.wx_update) # 初始化配置
  else:
   dlg.operato.config_item(dlg.Config, dlg.wx_create) # 初始化配置
 
  self.trigger.emit()

说实话还是蛮喜欢python的这种简洁的写法的,所以在很长的一段时间里,一直是比较注重代码的简洁度与良好的注释。em...,不过在其它语言中很难保持这种初心,现在是比较注重性能,响应时间,并发、安全等问题。

这里的interface是主窗口类,如果想在自己的窗口中实现,加一个RunThread类,并在主窗口中定义一个函数,用于调用Work类方法就可以了。通过代码可以看到,不到50行的代码就实现了方法一中的功能了。pyqt5有很多自己的方法,包括多线程等等。这里提供的是一种思路。当然还有很多种方式实现,大家可以去探索一下,好的方法可以一起分享讨论。

========================================7月24号更新=================================

先放一个效果图,

正常情况下会将一些耗时函数扔进Qthread线程中来避免页面假死的情况。

但并不是所有的都是行的通的,

当使用异步协程的时候,pyqt5推荐的是使用quamash

import sys
import asyncio
import time
 
from PyQt5.QtWidgets import QApplication, QProgressBar
from quamash import QEventLoop, QThreadExecutor
 
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop) # NEW must set the event loop
 
progress = QProgressBar()
progress.setRange(0, 99)
progress.show()
 
async def master():
 await first_50()
 with QThreadExecutor(1) as exec:
  await loop.run_in_executor(exec, last_50)
 # TODO announce completion?
 
async def first_50():
 for i in range(50):
  progress.setValue(i)
  await asyncio.sleep(.1)
 
def last_50():
 for i in range(50,100):
  loop.call_soon_threadsafe(progress.setValue, i)
  time.sleep(.1)
 
with loop: ## context manager calls .close() when loop completes, and releases all resources
 loop.run_until_complete(master())

还有一种情况,就是在UI主线程中执行,需要注意的是,如果是耗时任务则会造成界面的卡死,并不大友好。

到此这篇关于PyQt5 界面显示无响应的实现的文章就介绍到这了,更多相关PyQt5 界面显示无响应内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python中byte字符串转string的实现

    Python中byte字符串转string的实现

    本文主要介绍了Python中byte字符串转string的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Python实现设计模式之单例模式详解

    Python实现设计模式之单例模式详解

    这篇文章主要介绍了Python实现设计模式之单例模式详解,设计模式是指软件设计问题的推荐方案,设计模式一般是描述如何组织代码和使用最佳实践来解决常见的设计问题,需谨记一点:设计模式是高层次的方案,并不关注具体的实现细节,比如算法和数据结构,需要的朋友可以参考下
    2023-09-09
  • Python常用随机数与随机字符串方法实例

    Python常用随机数与随机字符串方法实例

    这篇文章主要介绍了Python常用随机数与随机字符串方法实例,本文讲解了随机整数、随机选取0到100间的偶数、随机浮点数、随机字符串等常用随机方法,需要的朋友可以参考下
    2015-04-04
  • 如何使用Python实现一个简易的ORM模型

    如何使用Python实现一个简易的ORM模型

    ORM(Object Relational Mapping)是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。本文将介绍如何使用Python实现一个简易的ORM
    2021-05-05
  • 详解Python字符串原理与使用的深度总结

    详解Python字符串原理与使用的深度总结

    本文将学习字符串数据类型相关知识,将讨论如何声明字符串数据类型,字符串数据类型与 ASCII 表的关系,字符串数据类型的属性,以及一些重要的字符串方法和操作,超级干货,不容错过
    2022-05-05
  • python list数据等间隔抽取并新建list存储的例子

    python list数据等间隔抽取并新建list存储的例子

    今天小编就为大家分享一篇python list数据等间隔抽取并新建list存储的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • Python使用selenium实现网页用户名 密码 验证码自动登录功能

    Python使用selenium实现网页用户名 密码 验证码自动登录功能

    这篇文章主要介绍了Python使用selenium实现网页用户名 密码 验证码自动登录功能,实现思路很简单,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-05-05
  • Python opencv缺陷检测的实现及问题解决

    Python opencv缺陷检测的实现及问题解决

    这篇文章主要介绍了Python opencv缺陷检测的实现及问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • 基于Python实现网页文章转PDF文档

    基于Python实现网页文章转PDF文档

    有时候看到一篇好的文章,想去保存下来,传统方式一般是收藏书签、复制粘贴到文档或者直接复制链接保存,但这也太麻烦了。本文将用Python语言实现将网上的文章转存为PDF文档,保存电脑上慢慢看
    2022-05-05
  • Jupyter安装链接aconda实现过程图解

    Jupyter安装链接aconda实现过程图解

    这篇文章主要介绍了Jupyter安装链接aconda实现过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11

最新评论