详解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 Web开发框架Django
Jun 30 Python
Python实现查找系统盘中需要找的字符
Jul 14 Python
python3.5 + PyQt5 +Eric6 实现的一个计算器代码
Mar 11 Python
python利用MethodType绑定方法到类示例代码
Aug 27 Python
python使用response.read()接收json数据的实例
Dec 19 Python
Pytorch Tensor的统计属性实例讲解
Dec 30 Python
pytorch进行上采样的种类实例
Feb 18 Python
Python Numpy,mask图像的生成详解
Feb 19 Python
Python多进程编程常用方法解析
Mar 26 Python
PageFactory设计模式基于python实现
Apr 14 Python
使用Keras预训练模型ResNet50进行图像分类方式
May 23 Python
python中使用.py配置文件的方法详解
Nov 23 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中global和$GLOBALS[]的分析之一
2012/02/02 PHP
PHP发送AT指令实例代码
2016/05/26 PHP
php实现水印文字和缩略图的方法示例
2016/12/29 PHP
PHP递归实现文件夹的复制、删除、查看大小操作示例
2017/08/11 PHP
Mootools 1.2教程 同时进行多个形变动画
2009/09/15 Javascript
Bootstrap每天必学之基础排版
2015/11/20 Javascript
JS中Eval解析JSON字符串的一个小问题
2016/02/21 Javascript
原生JavaScript实现Ajax的方法
2016/04/07 Javascript
获取input标签的所有属性的方法
2016/06/28 Javascript
jQuery实现的自动加载页面功能示例
2016/09/04 Javascript
详解javascript表单的Ajax提交插件的使用
2016/12/29 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
2017/02/05 Javascript
Angular.JS利用ng-disabled属性和ng-model实现禁用button效果
2017/04/05 Javascript
关于vue.js过渡css类名的理解(推荐)
2017/04/10 Javascript
HTML5+Canvas调用手机拍照功能实现图片上传(下)
2017/04/21 Javascript
微信小程序自定义音乐进度条的实例代码
2018/08/28 Javascript
Vuejs学习笔记之使用指令v-model完成表单的数据双向绑定
2019/04/29 Javascript
解决vue-cli输入命令vue ui没效果的问题
2020/11/17 Javascript
Python字符串逐字符或逐词反转方法
2015/05/21 Python
Django基于ORM操作数据库的方法详解
2018/03/27 Python
Python实现一个带权无回置随机抽选函数的方法
2019/07/24 Python
Python图像处理模块ndimage用法实例分析
2019/09/05 Python
pytorch中的上采样以及各种反操作,求逆操作详解
2020/01/03 Python
Python 支持向量机分类器的实现
2020/01/15 Python
Python Scrapy框架:通用爬虫之CrawlSpider用法简单示例
2020/04/11 Python
tensorflow实现残差网络方式(mnist数据集)
2020/05/26 Python
html5中的一些标签学习(心得)
2016/10/18 HTML / CSS
Brookstone美国官网:独特新奇产品
2017/03/04 全球购物
京东奢侈品:全球奢侈品牌
2018/03/17 全球购物
世界闻名的衬衫制造商:Savile Row Company
2018/07/30 全球购物
Bally巴利中国官网:经典瑞士鞋履、手袋及配饰奢侈品牌
2018/10/09 全球购物
职业生涯规划书怎么写?
2014/09/14 职场文书
员工拾金不昧表扬稿
2015/05/05 职场文书
Python+Appium实现自动抢微信红包
2021/05/21 Python
一篇文章告诉你如何实现Vue前端分页和后端分页
2022/02/18 Vue.js
Go语言怎么使用变长参数函数
2022/07/15 Golang