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 界面显示无响应内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python GUI库图形界面开发之PyQt5控件QTableWidget详细使用方法与属性

    QTableWidget介绍 QTableWidget是Qt程序中常用的显示数据表格的控件,类似于c#中的DataGrid.QTableWidget是QTableView的子类,它使用标准的数据模型,并且其单元数据是通过QTableWidgetItem对象来实现的,使用QTableWidget时就需要QTableWidgetItem.用来表示表格中的一个单元格,整个表格就是用各个单元格构建起来的 QTableWidget类中的常用方法 方法 描述 setROwCount(int row) 设置Q

  • pyqt5使用按钮进行界面的跳转方法

    简介 进行按钮进行界面的跳转,我这里面我介绍两种,一种是没有使用Qtdesigner的代码,另一种是使用Qtdesigner的代码 代码1 import sys from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication class First(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.

  • pyqt5实现登录界面的模板

    本文实例为大家分享了pyqt5登录界面的实现模板,供大家参考,具体内容如下 说明 本例,展示了通过登录界面打开主界面的实现方式. 其中,登录的账号与密码判断都比较简单,请大家根据自己需要,自行完善补充. [如下代码,完全复制,直接运行,即可使用] import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * ################################

  • pyqt5利用pyqtDesigner实现登录界面

    本文实例为大家分享了pyqt5利用pyqtDesigner实现登录界面的具体代码,供大家参考,具体内容如下 为便于操作 界面和逻辑分离 逻辑类: import sys import pymysql from loginUI import * //导入 from PyQt5.QtWidgets import * from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5.QtCore import * from PyQt5.QtGui import

  • python GUI库图形界面开发之PyQt5树形结构控件QTreeWidget详细使用方法与实例

    PyQt5树形结构控件QTreeWidget简介 QTreeWidget 类根据预设的模型提供树形显示控件. QTreeWidget 使用类似于 QListView 类的方式提供一种典型的基于 item 的树形交互方法类,该类基于QT的"模型/视图"结构,提供了默认的模型来支撑 item 的显示,这些 item 类为 QTreeWidgetItem 类. 如果不需要灵活的"模型/视图"框架,可以使用QTreeWidget 来创建有层级关系的树形结构.当把标准 ite

  • pyQt5实时刷新界面的示例

    如下所示: from PyQt5.QtCore import QThread , pyqtSignal, QDateTime , QObject from PyQt5.QtWidgets import QApplication, QDialog, QLineEdit import time import sys class BackendThread(QObject): # 通过类成员对象定义信号 update_date = pyqtSignal(str) # 处理业务逻辑 def run(se

  • python GUI库图形界面开发之PyQt5表格控件QTableView详细使用方法与实例

    PyQt5表格控件QTableView简介 在通常情况下,一个应用需要和一批数据进行交互,然后以表格的形式输出这些信息,这时就需要用到QTableView类了,在QTableView中可以使用自定义的数据模型来显示内容,通过setModel来绑定数据源 QTableWidget继承自QTableView,主要区别是QTableView可以使用自定义的数据模型来显示内容(先通setModel来绑定数据源),而QTableWidget自能使用标准的数据模型,并且其单元格数据是通过QTableWidg

  • python GUI库图形界面开发之PyQt5下拉列表框控件QComboBox详细使用方法与实例

    PyQt5下拉列表框控件QComboBox介绍 QComboBox是一个集按钮和下拉选项于一体的控件,也称做下拉列表框 QComboBox类中的常用方法如表 方法 描述 addItem() 添加一个下拉选项 addItems() 从列表中添加下拉选项 Clear() 删除下拉选项集合中的所有选项 count() 返回下拉选项集合中的数目 currentText() 返回选中选项的文本 itemText(i) 获取索引为i的item的选项文本 currentIndex() 返回选中项的索引 set

  • python GUI库图形界面开发之PyQt5浏览器控件QWebEngineView详细使用方法

    PyQt5浏览器控件QWebEngineView PyQt5使用QWebEngineView控件来展示HTML页面,对老版本的QWebView类不在进行维护,因为QWebEngineView使用CHromium内核可以给用户带来更好的体验 QWebEngineView类中常用方法 方法 描述 load(QUrl url) 加载指定的URL并显示 setHtml(QString&html) 将网页视图的内容设置为指定的HTML内容 QWebEngineView控件使用load()函数加载一个Web

  • PyQt5 界面显示无响应的实现

    在GUI程序中,主线程也叫GUI线程,因为它是唯一被允许执行GUI相关操作的线程.对于一些耗时的操作,如果放在主线程中,就是出现界面无法响应的问题. 界面假死分析 在编写QT的界面程序时,当我们调用QApplication.exec()时,我们就启动了QT的事件循环.在开始的时候,QT会发出一些事件来显示和绘制窗口部件.在这之后,事件循环就开始运行,不断地检查是不是有事件发生并且把这些事件发送给应用程序中的QObject. 当一个事件被处理时,其他事件也可能会产生并且追加到QT的事件队列中.如果

  • Android ListView的item背景色设置和item点击无响应的解决方法

    下面讲解以下在使用listview时最常见的几个问题.1.如何改变item的背景色和按下颜色 listview默认情况下,item的背景色是黑色,在用户点击时是黄色的.如果需要修改为自定义的背景颜色,一般情况下有三种方法: 1)设置listSelector 2)在布局文件中设置item的background 3)在adapter的getview中设置 这三种方法都能达到改变item默认的背景色和按下颜色,下面来分别讲解,但是在这之前需要先写好selector.xml文件; 复制代码 代码如下:

  • jQuery on()方法绑定动态元素的点击事件无响应的解决办法

    $('#check_all').on('click' , function(){ alert(1); }); $("#yujinlist").append(html); count++; } 以上代码执行时,点击#check_all时,alert一直没反应,后在网上查资料时,才知道on前面的元素也必须在页面加载的时候就存在于dom里面, 那原话是这样的: 支持给动态元素和属性绑定事件的是live和on,其中live在JQUERY 1.7之后就不推荐使用了.现在主要用on,使用on的时候

  • cloudstack下libvirtd服务无响应问题

    在cloudstack4.5.2版本下,偶尔出现libvirtd服务无响应的情况,导致virsh命令无法使用,同时伴随cloudstack master丢失该slave主机连接的情况.最初怀疑是libvirtd服务或版本的问题,经过分析和排查最终确定是cloudstack-agent的问题.但是在官网上并没有找到类似的bug提交,该问题可能还存在于更高的版本,需要时间进一步从根本上分析.下面是该问题的处理过程,在此记录下,关注和使用cloudstack的朋友可以参考. 众所周知,cloudsta

  • Android开发中避免应用无响应的方法(Application Not Responding、ANR)

    App里发生的最糟糕的事是弹出应用无响应"Application Not Responding" (ANR) 对话框.本课讲的是如何保持应用响应,避免ANR. 什么触发ANR 通常,系统会在应用无法对用户输入响应时显示ANR.比如,如果一个应用在I/O操作上阻塞了(频繁请求网络)UI线程,系统无法处理用户输入事件.或者,在UI线程中,app花了大量时间在构建复杂的类,或在游戏中计算下一个动作.保证这些操作高效是很重要的,但最高效的代码也需要花费时间. 在任何情况下,都不要在UI线程执行

  • 为vue-router懒加载时下载js的过程中添加loading提示避免无响应问题

    用过vue-router都知道它可以实现模块js的懒加载,即只有当需要时才去加载对应模块的js脚本文件,以加速主页的显示.比如只有第一次用户点击某个"用户信息"按钮或菜单时,才下载"用户信息"这个模块的js组件. 懒加载的实现,依赖与webpack下AMD模式require函数的功能.webpack会将异步require的文件生成一个独立的js文件,调用时异步下载这个js且在完成后再执行它.开发项目中实现的关键代码是: const basicInfo = { pat

  • 关于python下cv.waitKey无响应的原因及解决方法

    按下键的时候,焦点要落在窗口上,不能落在cmd窗口上. 另外,一般在imshow()后要使用waitKey(),给图像绘制留下时间,不然窗口会出现无响应情况,并且图像无法显示出来. int waitKey(int delay=0) - 延时delay = 0 函数则延时无限长,必须有键按下才继续执行. - 延时delay > 0 函数返回值为按下的键的ASCII码值,超时则返回-1. OpenCV: waitKey waitKey Waits for a pressed key. C++: in

  • iOS UIButton 点击无响应的解决办法

    前言 在日常开发中我们经常和按钮打交道,但是有时候会碰到比较难处理的问题,就是按钮不响应点击事件,这时候我们需要从下面几方面排查 按钮不响应的原因 1.按钮添加到了一个没有开启用户交互的父View上,例如UIImageView,这时候开启父试图的交互 view.userInteractionEnabled = YES 设为YES就可以解决问题 2.按钮自身被遮挡,点击的时候根本就没有点击到button,而是他上面一层View,自然就不会响应 这里有个看图层的方法,下图点击那个红框的按钮就可以看到

  • 易语言假死无响应采用处理事件解决办法

    处理事件() 一个比较简单的理解是:让程序反应过来 这个函数一般是用在延时前面或后面,如果不用的话程序很容易形成假死,造成程序无响应 如下图,虽然这个程序还在运行,但是界面上东西是显示不了的,比如标签,编辑框,画板,会有一个圆圈转啊转 加了处理事件() 就可以避免这种情况, 可以试试看,在一个计次循环或者判断循环里使用延时函数,然后分别在后面加上处理事件() 和不加处理事件() . 位置可以放在处理事件的前面或后面,效果一样,感谢大家对我们的支持.

  • python定时检测无响应进程并重启的实例代码

    总有一些程序在windows平台表现不稳定,动不动一段时间就无响应,但又不得不用,每次都是发现问题了手动重启,现在写个脚本定时检测进程是否正常,自动重启. 涉及知识点 schedule定时任务调度 os.popen运行程序并读取解析运行结果 代码分解 脚本主入口 if __name__ == '__main__': #每5秒执行检查任务 schedule.every(5).seconds.do(check_job) #此处固定写法,意思是每秒钟schedule看下是否有pending的任务,有就

随机推荐