详解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实现探测socket和web服务示例
Mar 28 Python
pyqt5自定义信号实例解析
Jan 31 Python
django如何连接已存在数据的数据库
Aug 14 Python
django+echart绘制曲线图的方法示例
Nov 26 Python
Python实现连接MySql数据库及增删改查操作详解
Apr 16 Python
Python3模拟curl发送post请求操作示例
May 03 Python
三步实现Django Paginator分页的方法
Jun 11 Python
获取django框架orm query执行的sql语句实现方法分析
Jun 20 Python
django 微信网页授权认证api的步骤详解
Jul 30 Python
python super的使用方法及实例详解
Sep 25 Python
Python 函数绘图及函数图像微分与积分
Nov 20 Python
Python底层封装实现方法详解
Jan 22 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 md5下16位和32位的实现代码
2008/04/09 PHP
php一句话cmdshell新型 (非一句话木马)
2009/04/18 PHP
php+mysql实现简单的增删改查功能
2015/07/13 PHP
PHP使用Mysqli类库实现完美分页效果的方法
2016/04/07 PHP
thinkPHP中volist标签用法示例
2016/12/06 PHP
许愿墙中用到的函数
2006/10/07 Javascript
Javascript 网页水印(非图片水印)实现代码
2010/03/01 Javascript
js open() 与showModalDialog()方法使用介绍
2013/09/10 Javascript
jquery 缓存问题的几个解决方法
2013/11/11 Javascript
node.js超时timeout详解
2014/11/26 Javascript
JavaScript中实现单体模式分享
2015/01/29 Javascript
JavaScript获取数组最小值和最大值的方法
2015/06/09 Javascript
jquery 获取select数组与name数组长度的实现代码
2016/06/20 Javascript
jQuery实现图片轮播效果代码
2016/09/27 Javascript
vue2.0开发实践总结之入门篇
2016/12/06 Javascript
vuejs绑定class和style样式
2017/04/11 Javascript
基于javascript 显式转换与隐式转换(详解)
2017/12/15 Javascript
vue-cli中安装方法(图文详细步骤)
2018/12/12 Javascript
详解vue中使用transition和animation的实例代码
2020/12/12 Vue.js
[02:35]DOTA2超级联赛专访XB 难忘一年九冠称王
2013/06/20 DOTA
Python写的服务监控程序实例
2015/01/31 Python
Python中使用支持向量机(SVM)算法
2017/12/26 Python
浅谈Tensorflow模型的保存与恢复加载
2018/04/26 Python
kaggle+mnist实现手写字体识别
2018/07/26 Python
在Python中关于使用os模块遍历目录的实现方法
2019/01/03 Python
python实现视频分帧效果
2019/05/31 Python
Python绘制动态水球图过程详解
2020/06/03 Python
python selenium 获取接口数据的实现
2020/12/07 Python
CSS3 Backgrounds属性相关介绍
2011/05/11 HTML / CSS
amaze ui 的使用详细教程
2020/08/19 HTML / CSS
英国布鲁姆精品店:Bloom Boutique
2018/03/01 全球购物
澳大利亚最大的在线美发和美容零售商之一:My Hair Care & Beauty
2019/08/24 全球购物
绩效专员岗位职责
2013/12/02 职场文书
中国好声音华少广告词
2014/03/17 职场文书
教你怎么用Python操作MySql数据库
2021/05/31 Python
漫画「处刑少女的生存之道」第3卷封面公开
2022/03/21 日漫