详解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实现在目录中查找指定文件的方法
Nov 11 Python
Python验证企业工商注册码
Oct 25 Python
python中执行shell的两种方法总结
Jan 10 Python
浅谈django开发者模式中的autoreload是如何实现的
Aug 18 Python
Appium Python自动化测试之环境搭建的步骤
Jan 23 Python
python使用wxpy实现微信消息防撤回脚本
Apr 29 Python
对django中foreignkey的简单使用详解
Jul 28 Python
django将数组传递给前台模板的方法
Aug 06 Python
nginx黑名单和django限速,最简单的防恶意请求方法分享
Aug 09 Python
使用Python画出小人发射爱心的代码
Nov 23 Python
Python 批量读取文件中指定字符的实现
Mar 06 Python
教你用python实现一个无界面的小型图书管理系统
May 21 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发送邮件类代码附详细说明
2008/07/10 PHP
php中利用explode函数分割字符串到数组
2014/02/08 PHP
分享PHP计算两个日期相差天数的代码
2015/12/23 PHP
编写PHP程序检查字符串中的中文字符个数的实例分享
2016/03/17 PHP
PHP实现数组array转换成xml的方法
2016/07/19 PHP
php使用get_class_methods()函数获取分类的方法
2016/07/20 PHP
thinkphp5.0自定义验证规则使用方法
2017/11/16 PHP
PHP接入微信H5支付的方法示例
2019/10/28 PHP
jQuery的Ajax时无响应数据的解决方法
2010/05/25 Javascript
基于jquery的滑动样例代码
2010/11/20 Javascript
js解析xml字符串和xml文档实现原理及代码(针对ie与火狐)
2013/02/02 Javascript
Javascript 遮罩层和加载效果代码
2013/08/01 Javascript
js拼接html注意问题示例探讨
2014/07/14 Javascript
javascript实现状态栏文字首尾相接循环滚动的方法
2015/07/22 Javascript
jQuery基于json与cookie实现购物车的方法
2016/04/15 Javascript
JavaScript自定义文本框光标
2017/03/05 Javascript
解决JavaScript中0.1+0.2不等于0.3问题
2018/10/23 Javascript
关于Vue Router中路由守卫的应用及在全局导航守卫中检查元字段的方法
2018/12/09 Javascript
原生JS forEach()和map()遍历的区别、兼容写法及jQuery $.each、$.map遍历操作
2019/02/27 jQuery
vue动态配置模板 'component is'代码
2019/07/04 Javascript
Python XML转Json之XML2Dict的使用方法
2019/01/15 Python
django数据关系一对多、多对多模型、自关联的建立
2019/07/24 Python
使用Python和百度语音识别生成视频字幕的实现
2020/04/09 Python
如何用用Python将地址标记在地图上
2021/02/07 Python
HTML5 HTMLCollection和NodeList的区别详解
2020/04/29 HTML / CSS
英国领先的体验日提供商:Buyagift
2019/04/19 全球购物
倩碧澳大利亚官网:Clinique澳大利亚
2019/07/22 全球购物
《小小雨点》教学反思
2014/02/18 职场文书
人力资源作业细则
2014/03/03 职场文书
学习朴航瑛老师爱岗敬业先进事迹思想汇报
2014/09/17 职场文书
2015年全国爱眼日活动小结
2015/02/27 职场文书
同学聚会通知书
2015/04/20 职场文书
民事上诉状范文
2015/05/22 职场文书
环保守法证明
2015/06/24 职场文书
党员电教片《信仰》心得体会
2016/01/15 职场文书
win10重装系统后上不了网怎么办 win10重装系统网络故障的解决办法
2022/07/23 数码科技