详解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 splitlines使用技巧
Sep 06 Python
python利用elaphe制作二维条形码实现代码
May 25 Python
linux下安装easy_install的方法
Feb 10 Python
python3抓取中文网页的方法
Jul 28 Python
Python pymongo模块用法示例
Mar 31 Python
Python中py文件引用另一个py文件变量的方法
Apr 29 Python
Python 单元测试(unittest)的使用小结
Nov 14 Python
python excel转换csv代码实例
Aug 26 Python
python如何从键盘获取输入实例
Jun 18 Python
Python使用Selenium实现淘宝抢单的流程分析
Jun 23 Python
Python 通过正则表达式快速获取电影的下载地址
Aug 17 Python
13个Pandas实用技巧,助你提高开发效率
Aug 19 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中strtotime函数用法详解
2014/11/15 PHP
javascript数组组合成字符串的脚本
2021/01/06 Javascript
网页前台通过js非法字符过滤代码(骂人的话等等)
2010/05/26 Javascript
Jquery动态添加及删除页面节点元素示例代码
2014/06/16 Javascript
jQuery的deferred对象详解
2014/11/12 Javascript
javascript实现禁止右键和F12查看源代码
2014/12/26 Javascript
jsMind通过鼠标拖拽的方式调整节点位置
2015/04/13 Javascript
简介JavaScript中Boolean.toSource()方法的使用
2015/06/05 Javascript
学习javascript面向对象 理解javascript对象
2016/01/04 Javascript
angular-ngSanitize模块-$sanitize服务详解
2017/06/13 Javascript
Angularjs上传图片实例详解
2017/08/06 Javascript
js定义类的方法示例【ES5与ES6】
2019/07/30 Javascript
vue中使用element组件时事件想要传递其他参数的问题
2019/09/18 Javascript
Vue前端项目部署IIS的实现
2020/01/06 Javascript
前端vue如何使用高德地图
2020/11/05 Javascript
[01:34]2016国际邀请赛中国区预选赛IG战队教练采访
2016/06/27 DOTA
python 调用c语言函数的方法
2017/09/29 Python
对Python 3.2 迭代器的next函数实例讲解
2018/10/18 Python
ubuntu 18.04 安装opencv3.4.5的教程(图解)
2019/11/04 Python
tensorflow获取预训练模型某层参数并赋值到当前网络指定层方式
2020/01/24 Python
PyInstaller的安装和使用的详细步骤
2020/06/02 Python
解析Tensorflow之MNIST的使用
2020/06/30 Python
浅谈Python __init__.py的作用
2020/10/28 Python
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
中国一家专注拼团的社交购物网站:拼多多
2018/06/13 全球购物
在校生党员自我评价
2013/09/25 职场文书
广告学专业推荐信范文
2013/11/23 职场文书
《最后的姿势》教学反思
2014/02/27 职场文书
宪法宣传周工作方案
2014/05/26 职场文书
赔偿协议书范本
2014/09/12 职场文书
公安纪律作风整顿剖析材料
2014/10/10 职场文书
2016学雷锋优秀志愿者事迹材料
2016/02/25 职场文书
感谢信
2019/04/11 职场文书
自荐信范文
2019/05/20 职场文书
公文写作:工伤事故分析报告怎么写?
2019/11/05 职场文书
详解PHP设计模式之依赖注入模式
2021/05/25 PHP