详解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中的异常处理
Apr 28 Python
利用python批量检查网站的可用性
Sep 09 Python
python WindowsError的错误代码详解
Jul 23 Python
python中利用zfill方法自动给数字前面补0
Apr 10 Python
python 删除列表里所有空格项的方法总结
Apr 18 Python
python 实现selenium断言和验证的方法
Feb 13 Python
用Python批量把文件复制到另一个文件夹的实现方法
Aug 16 Python
python爬虫之爬取百度音乐的实现方法
Aug 24 Python
opencv3/C++实现视频读取、视频写入
Dec 11 Python
对tensorflow中tf.nn.conv1d和layers.conv1d的区别详解
Feb 11 Python
Python 统计位数为偶数的数字代码详解
Mar 15 Python
Python实现socket库网络通信套接字
Jun 04 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
2006/12/23 PHP
ThinkPHP实现非标准名称数据表快速创建模型的方法
2014/11/29 PHP
php设计模式之单例模式用法经典示例分析
2019/09/20 PHP
JavaScript动态调整TextArea高度的代码
2010/12/28 Javascript
Jquery实现弹出层分享微博插件具备动画效果
2013/04/03 Javascript
jQuery中filter()和find()的区别深入了解
2013/09/25 Javascript
使用jquery animate创建平滑滚动效果(可以是到顶部、到底部或指定地方)
2014/05/27 Javascript
jquery实现实时改变网页字体大小、字体背景色和颜色的方法
2015/08/05 Javascript
JavaScript的ExtJS框架中表格的编写教程
2016/05/21 Javascript
React实现双向绑定示例代码
2016/09/19 Javascript
基于angular中的重要指令详解($eval,$parse和$compile)
2016/10/21 Javascript
js date 格式化
2017/02/15 Javascript
借助node实战JSONP跨域实例
2017/03/30 Javascript
JS实现移动端实时监听输入框变化的实例代码
2017/04/12 Javascript
ReactNative Image组件使用详解
2017/08/07 Javascript
javascript基础进阶_深入剖析执行环境及作用域链
2017/09/05 Javascript
JS实现求字符串中出现最多次数的字符和次数示例
2019/07/05 Javascript
JavaScript对象原型链原理详解
2020/02/05 Javascript
vue-router之解决addRoutes使用遇到的坑
2020/07/19 Javascript
Python中的yield浅析
2014/06/16 Python
详解Python的Django框架中的通用视图
2015/05/04 Python
python写入xml文件的方法
2015/05/08 Python
Django实现支付宝付款和微信支付的示例代码
2018/07/25 Python
对Tensorflow中的矩阵运算函数详解
2018/07/27 Python
浅析Python四种数据类型
2018/09/26 Python
python3+requests接口自动化session操作方法
2018/10/13 Python
一行Python代码过滤标点符号等特殊字符
2019/08/12 Python
python2和python3实现在图片上加汉字的方法
2019/08/22 Python
Python 利用邮件系统完成远程控制电脑的实现(关机、重启等)
2019/11/19 Python
python使用协程实现并发操作的方法详解
2019/12/27 Python
在家更换处方镜片:Lensabl
2019/05/01 全球购物
KOHLER科勒美国官网:国际著名卫浴橱柜领先品牌
2020/06/27 全球购物
幼儿教师求职信
2014/05/24 职场文书
2014年预备党员端正入党动机思想汇报
2014/09/13 职场文书
授权委托书公证
2014/09/14 职场文书
Redis Cluster集群动态扩容的实现
2021/07/15 Redis