详解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中运算符使用时的优先级
May 14 Python
Python的Django框架中的URL配置与松耦合
Jul 15 Python
Python简单实现TCP包发送十六进制数据的方法
Apr 16 Python
完美解决Python2操作中文名文件乱码的问题
Jan 04 Python
Python 2.x如何设置命令执行的超时时间实例
Oct 19 Python
python使用Tesseract库识别验证
Mar 21 Python
朴素贝叶斯Python实例及解析
Nov 19 Python
Django框架自定义session处理操作示例
May 27 Python
使用Rasterio读取栅格数据的实例讲解
Nov 26 Python
解决python父线程关闭后子线程不关闭问题
Apr 25 Python
Django def clean()函数对表单中的数据进行验证操作
Jul 09 Python
Python识别处理照片中的条形码
Nov 16 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
WordPress分页伪静态加html后缀
2016/06/08 PHP
PHP获取页面执行时间的方法(推荐)
2016/12/10 PHP
laravel Task Scheduling(任务调度)在windows下的使用详解
2019/10/22 PHP
添加JavaScript重载函数的辅助方法2
2010/07/04 Javascript
IE6下js通过css隐藏select的一个bug
2010/08/16 Javascript
使用js+jquery实现无限极联动
2013/05/23 Javascript
node.js中的fs.truncate方法使用说明
2014/12/15 Javascript
js仿土豆网带缩略图的焦点图片切换效果实现方法
2015/02/23 Javascript
JavaScript编程中window的location与history对象详解
2015/10/26 Javascript
Node.js使用NodeMailer发送邮件实例代码
2017/03/06 Javascript
vue 虚拟dom的patch源码分析
2018/03/01 Javascript
vue2.0实现音乐/视频播放进度条组件
2018/06/06 Javascript
vue异步axios获取的数据渲染到页面的方法
2018/08/09 Javascript
JS实现指定区域的全屏显示功能示例
2019/04/25 Javascript
vue 引用自定义ttf、otf、在线字体的方法
2019/05/09 Javascript
微信小程序结合Storage实现搜索历史效果
2019/05/18 Javascript
[01:22:29]真视界:2019年国际邀请赛总决赛
2020/01/29 DOTA
详解Python的Django框架中的templates设置
2015/05/11 Python
Python中threading模块join函数用法实例分析
2015/06/04 Python
Python中使用OpenCV库来进行简单的气象学遥感影像计算
2016/02/19 Python
如何在django里上传csv文件并进行入库处理的方法
2019/01/02 Python
python django框架中使用FastDFS分布式文件系统的安装方法
2019/06/10 Python
Python安装tar.gz格式文件方法详解
2020/01/19 Python
python中使用paramiko模块并实现远程连接服务器执行上传下载功能
2020/02/29 Python
navabi英国:设计师大码女装
2019/06/25 全球购物
含精油的天然有机化妆品:Indemne
2019/08/27 全球购物
优秀民警事迹材料
2014/01/29 职场文书
《美丽的彩虹》教学反思
2014/02/25 职场文书
家长通知书教师评语
2014/04/17 职场文书
《乡下孩子》教学反思
2014/04/17 职场文书
青年志愿者活动总结
2014/04/26 职场文书
社区维稳工作方案
2014/06/06 职场文书
体育活动总结
2015/02/04 职场文书
2016年春季开学典礼新闻稿
2015/11/25 职场文书
MySQL系列之开篇 MySQL关系型数据库基础概念
2021/07/02 MySQL
向Spring IOC 容器动态注册bean实现方式
2022/07/15 Java/Android