详解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中__name__的使用实例
Apr 14 Python
Windows中安装使用Virtualenv来创建独立Python环境
May 31 Python
Python实现购物程序思路及代码
Jul 24 Python
pandas 小数位数 精度的处理方法
Jun 09 Python
python递归实现快速排序
Aug 18 Python
Python数据抓取爬虫代理防封IP方法
Dec 23 Python
python支付宝支付示例详解
Aug 22 Python
Python3实现二叉树的最大深度
Sep 30 Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
Nov 25 Python
python 计算方位角实例(根据两点的坐标计算)
Jan 17 Python
如何利用Python matplotlib绘制雷达图
Dec 21 Python
用Python制作灯光秀短视频的思路详解
Apr 13 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 之Section与Cookie使用总结
2012/09/14 PHP
php获取随机数组列表的方法
2014/11/13 PHP
php实现httpRequest的方法
2015/03/13 PHP
PHP标准类(stdclass)用法示例
2016/09/28 PHP
一直复略了的一个问题,关于表单重复提交
2007/02/15 Javascript
Open and Print a Word Document
2007/06/15 Javascript
[HTML/CSS/Javascript]WWTJS
2007/09/25 Javascript
extjs 04_grid 单击事件新发现
2012/11/27 Javascript
js实现图片轮播效果
2015/12/19 Javascript
jQuery Easyui datagrid连续发送两次请求问题
2016/12/13 Javascript
利用vue写todolist单页应用
2016/12/15 Javascript
nodejs+express实现文件上传下载管理网站
2017/03/15 NodeJs
Webpack中loader打包各种文件的方法实例
2019/09/03 Javascript
swiper4实现移动端导航切换
2020/10/16 Javascript
JavaScript自定义超时API代码实例
2020/04/30 Javascript
python实现的一只从百度开始不断搜索的小爬虫
2013/08/13 Python
Python使用迭代器打印螺旋矩阵的思路及代码示例
2016/07/02 Python
python计算两个数的百分比方法
2018/06/29 Python
Python实现的爬取小说爬虫功能示例
2019/03/30 Python
基于python的ini配置文件操作工具类
2019/04/24 Python
python实现坦克大战游戏 附详细注释
2020/03/27 Python
Python with标签使用方法解析
2020/01/17 Python
Python装饰器的应用场景代码总结
2020/04/10 Python
Python求凸包及多边形面积教程
2020/04/12 Python
python能在浏览器能运行吗
2020/06/17 Python
python自动化测试三部曲之request+django实现接口测试
2020/10/07 Python
CSS3实现的闪烁跳跃进度条示例(附源码)
2013/08/19 HTML / CSS
C++的几个面试题附答案
2016/08/03 面试题
学校运动会开幕演讲稿
2014/01/04 职场文书
迟到早退检讨书
2014/02/10 职场文书
4s店活动策划方案
2014/08/25 职场文书
作风转变年心得体会
2014/10/22 职场文书
2014年综治维稳工作总结
2014/11/17 职场文书
2014年教学管理工作总结
2014/12/02 职场文书
作文之亲情600字
2019/09/23 职场文书
Python数据分析之pandas读取数据
2021/06/02 Python