详解pyqt5 动画在QThread线程中无法运行问题


Posted in Python onMay 05, 2018

自己做了一个tcp工具,在学习动画的时候踩了坑,需求是根据上线变绿色,离线变灰色,如果连接断开了,则变为灰色

问题现象:

详解pyqt5 动画在QThread线程中无法运行问题

可以看到点击“连接”,“离线”的时候动画是正常的,但是当tcp超时断开后,虽然离线按钮变为连接了,却没有执行离线动画

关键源代码如下

class BSJTcpThread(QtCore.QThread):
  recv_signal = QtCore.pyqtSignal(str)
  send_signal = QtCore.pyqtSignal(str)

  def __init__(self, socketcp, onBtn, heartcheck, senBtn, scene):
    super().__init__()
    self.s = socketcp
    self.yqtool = Bianlifunction()
    self.onBtn = onBtn
    self.heartcheck = heartcheck
    self.sendBtn = senBtn
    self.scene1 = scene

  def run(self):
    """线程"""
    global stopsingle
    stopsingle = 0
    while 1:
      btcpreceive = self.s.recv(1024)
      tcpreceive1 = str(binascii.b2a_hex(btcpreceive), encoding="utf-8")

      tcpreceive = ""
      i = 0
      while i < len(tcpreceive1) - 1: # 十六进制数据处理,两个字节隔开
        if i == len(tcpreceive1) - 2:
          tcpreceive += tcpreceive1[i:i + 2]
          i += 2
        else:
          tcpreceive += tcpreceive1[i:i + 2] + " "
          i += 2

      if tcpreceive == "":
        stopsingle = 1
        self.s.shutdown(2)
        self.s.close()
        self.onBtn.setText("连接")
        self.scene1.offlineCol.start() # 启动离线动画
        self.heartcheck.setChecked(False)
        self.heartcheck.setVisible(False)
        self.sendBtn.setDisabled(True)
      else:
        self.recv_signal.emit(tcpreceive)
      if stopsingle == 1:
        break

然后再启动线程

self.tcpth = BSJTcpThread(self.s, self.onBtn, self.heartcheck, self.sendBtn, self.scene)
      self.tcpth.recv_signal.connect(self.fillrecvmsg)
      self.tcpth.send_signal.connect(self.fillsendmsg)
      self.tcpth.start()

问题点:

经过谷爹搜索,终于找到了问题原因详见https://stackoverflow.com/questions/44328750/pyqt-qgraphicscene-move-item-in-background-thread

大致原因就是QGraphics Scene 不是一个安全的线程对象,我们不能直接在线程中去改变主程序的状态,我们必须通过信号的方式去更新QGraphics

解决方法:

首先,我们编辑一个信号方法

def threadAnimate(self, message):
    if message == "1":
      self.scene.offlineCol.start()

然后添加相关信号槽

self.tcpth = BSJTcpThread(self.s, self.onBtn, self.heartcheck, self.sendBtn)
      self.tcpth.recv_signal.connect(self.fillrecvmsg)
      self.tcpth.send_signal.connect(self.fillsendmsg)
      self.tcpth.animate_signal.connect(self.threadAnimate) # 添加一个动画信号
      self.tcpth.start()

在线程中发出离线动画的信号

class BSJTcpThread(QtCore.QThread):
  recv_signal = QtCore.pyqtSignal(str)
  send_signal = QtCore.pyqtSignal(str)
  animate_signal = QtCore.pyqtSignal(str)

  def __init__(self, socketcp, onBtn, heartcheck, senBtn):
    super().__init__()
    self.s = socketcp
    self.yqtool = Bianlifunction()
    self.onBtn = onBtn
    self.heartcheck = heartcheck
    self.sendBtn = senBtn

  def run(self):
    """线程"""
    global stopsingle
    stopsingle = 0
    while 1:
      btcpreceive = self.s.recv(1024)
      tcpreceive1 = str(binascii.b2a_hex(btcpreceive), encoding="utf-8")

      tcpreceive = ""
      i = 0
      while i < len(tcpreceive1) - 1: # 十六进制数据处理,两个字节隔开
        if i == len(tcpreceive1) - 2:
          tcpreceive += tcpreceive1[i:i + 2]
          i += 2
        else:
          tcpreceive += tcpreceive1[i:i + 2] + " "
          i += 2

      if tcpreceive == "":
        stopsingle = 1
        self.s.shutdown(2)
        self.s.close()
        self.onBtn.setText("连接")
        self.animate_signal.emit("1")
        self.heartcheck.setChecked(False)
        self.heartcheck.setVisible(False)
        self.sendBtn.setDisabled(True)
      else:
        self.recv_signal.emit(tcpreceive)
      if stopsingle == 1:
        break

然后就可以了,这个和QThread多线程收发消息原理一样

详解pyqt5 动画在QThread线程中无法运行问题

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现批量修改文件名实例
Jul 08 Python
使用numpy和PIL进行简单的图像处理方法
Jul 02 Python
浅谈dataframe中更改列属性的方法
Jul 10 Python
python实现自动登录后台管理系统
Oct 18 Python
Python类的绑定方法和非绑定方法实例解析
Mar 04 Python
Python求解排列中的逆序数个数实例
May 03 Python
python如何安装下载后的模块
Jul 03 Python
使用Python中tkinter库简单gui界面制作及打包成exe的操作方法(二)
Oct 12 Python
Opencv常见图像格式Data Type及代码实例
Nov 02 Python
python实现简易名片管理系统
Apr 11 Python
Python 流媒体播放器的实现(基于VLC)
Apr 28 Python
使用numpy nonzero 找出非0元素
May 14 Python
python中in在list和dict中查找效率的对比分析
May 04 #Python
Django如何配置mysql数据库
May 04 #Python
Python实现求一个集合所有子集的示例
May 04 #Python
python list是否包含另一个list所有元素的实例
May 04 #Python
Python判断两个list是否是父子集关系的实例
May 04 #Python
python判断一个集合是否为另一个集合的子集方法
May 04 #Python
python3 判断列表是一个空列表的方法
May 04 #Python
You might like
php REMOTE_ADDR之获取访客IP的代码
2008/04/22 PHP
Apache 配置详解(最好的APACHE配置教程)
2010/07/04 PHP
php提示undefined index的几种解决方法
2012/05/21 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
再谈PHP中单双引号的区别详解
2016/06/12 PHP
PHP实现登录搜狐广告获取广告联盟数据的方法【附demo源码】
2016/10/14 PHP
PHP explode()函数用法讲解
2019/02/15 PHP
jQuery中:contains选择器用法实例
2014/12/30 Javascript
jquery实现增加删除行的方法
2015/02/03 Javascript
浅谈js的ajax的异步和同步请求的问题
2016/10/07 Javascript
Angular2开发——组件规划篇
2017/03/28 Javascript
BootStrap数据表格实例代码
2017/09/13 Javascript
jQuery封装animate.css的实例
2018/01/04 jQuery
webpack 插件html-webpack-plugin的具体使用
2018/04/09 Javascript
使用json-server简单完成CRUD模拟后台数据的方法
2018/07/12 Javascript
JavaScript实现简易计算器小功能
2020/10/22 Javascript
Python实现的简单hangman游戏实例
2015/06/28 Python
python django使用haystack:全文检索的框架(实例讲解)
2017/09/27 Python
python2爬取百度贴吧指定关键字和图片代码实例
2019/08/14 Python
如何利用Python 进行边缘检测
2020/10/14 Python
CSS3伪类选择器:nth-child()
2009/04/02 HTML / CSS
英国最大的体育&时尚零售公司:JD Sports
2017/12/13 全球购物
无畏的旅行:Intrepid Travel
2017/12/20 全球购物
戴尔新加坡官网:Dell Singapore
2020/12/13 全球购物
家长给小学生的评语
2014/01/30 职场文书
开学寄语大全
2014/04/08 职场文书
项目建议书模板
2014/05/12 职场文书
倡议书格式模板
2014/05/13 职场文书
大学新闻系应届生求职信
2014/06/02 职场文书
2014年机关党委工作总结
2014/12/11 职场文书
优秀班主任申报材料
2014/12/16 职场文书
创先争优个人总结
2015/03/04 职场文书
初中运动会前导词
2015/07/20 职场文书
银行文明优质服务培训心得体会
2016/01/09 职场文书
庭外和解协议书
2016/03/23 职场文书
Python基本的内置数据类型及使用方法
2022/04/13 Python