详解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爬虫模拟登录带验证码网站
Jan 22 Python
python版微信跳一跳游戏辅助
Jan 11 Python
django限制匿名用户访问及重定向的方法实例
Feb 07 Python
利用python 更新ssh 远程代码 操作远程服务器的实现代码
Feb 08 Python
Python实现正整数分解质因数操作示例
Aug 01 Python
浅谈Python3中strip()、lstrip()、rstrip()用法详解
Apr 29 Python
python 实现保存最新的三份文件,其余的都删掉
Dec 22 Python
通过Python实现一个简单的html页面
May 16 Python
Python打印不合法的文件名
Jul 31 Python
Python fileinput模块如何逐行读取多个文件
Oct 05 Python
python基础之错误和异常处理
Oct 24 Python
pytest实现多进程与多线程运行超好用的插件
Jul 15 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自动更新新闻DIY
2006/10/09 PHP
win2003服务器使用WPS的COM组件的一些问题解决方法
2012/01/11 PHP
PHP使用pear自带的mail类库发邮件的方法
2015/07/08 PHP
54个提高PHP程序运行效率的方法
2015/07/19 PHP
jQuery ajax cache缓存问题
2010/07/01 Javascript
zepto.js中tap事件阻止冒泡的实现方法
2015/02/12 Javascript
js针对ip地址、子网掩码、网关的逻辑性判断
2016/01/06 Javascript
通用无限极下拉菜单的实现代码
2016/05/31 Javascript
Jquery和BigFileUpload实现大文件上传及进度条显示
2016/06/27 Javascript
JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法
2017/01/18 Javascript
JS中跳出循环的示例代码
2017/09/14 Javascript
原生JS实现Ajax跨域请求flask响应内容
2017/10/24 Javascript
详解vue.js之props传递参数
2017/12/12 Javascript
详解如何在nuxt中添加proxyTable代理
2018/08/10 Javascript
使用node.js实现微信小程序实时聊天功能
2018/08/13 Javascript
jQuery实现每日秒杀商品倒计时功能
2019/09/06 jQuery
在NodeJs中使用node-schedule增加定时器任务的方法
2020/06/08 NodeJs
如何在selenium中使用js实现定位
2020/08/18 Javascript
javascript贪吃蛇游戏设计与实现
2020/09/17 Javascript
Python异常处理总结
2014/08/15 Python
python实现逻辑回归的方法示例
2017/05/02 Python
Python3.5 创建文件的简单实例
2018/04/26 Python
Flask和Django框架中自定义模型类的表名、父类相关问题分析
2018/07/19 Python
Python中的heapq模块源码详析
2019/01/08 Python
Python操作redis实例小结【String、Hash、List、Set等】
2019/05/16 Python
Python实现打砖块小游戏代码实例
2019/05/18 Python
python中wheel的用法整理
2020/06/15 Python
安装python3.7编译器后如何正确安装opnecv的方法详解
2020/06/16 Python
详解css3中dispaly的Grid布局与Flex布局
2020/09/11 HTML / CSS
英国婴儿和儿童服装网站:Vertbaudet
2018/04/02 全球购物
在校大学生自我评价范文
2014/09/12 职场文书
先进事迹材料怎么写
2014/12/30 职场文书
学术会议邀请函
2015/01/30 职场文书
党校学习个人总结
2015/02/15 职场文书
2016大学生社会实践单位评语
2015/12/01 职场文书
祝福语集锦:送给闺蜜的生日祝福语
2019/10/08 职场文书