详解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使用cookie库操保存cookie详解
Mar 03 Python
Python中用于去除空格的三个函数的使用小结
Apr 07 Python
Python正则表达式使用经典实例
Jun 21 Python
python中使用psutil查看内存占用的情况
Jun 11 Python
Python中一些深不见底的“坑”
Jun 12 Python
python 整数越界问题详解
Jun 27 Python
python pickle存储、读取大数据量列表、字典数据的方法
Jul 07 Python
Python图像处理模块ndimage用法实例分析
Sep 05 Python
TensorFlow tensor的拼接实例
Jan 19 Python
Python实现定时监测网站运行状态的示例代码
Sep 30 Python
Python WSGI 规范简介
Apr 11 Python
使用pd.merge表连接出现多余行的问题解决
Jun 16 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 正则判断中文UTF-8或GBK的思路及具体实现
2013/11/26 PHP
ThinkPHP3.1新特性之动态设置自动完成和自动验证示例
2014/06/19 PHP
教你如何开启shopnc b2b2c 伪静态
2014/10/21 PHP
php调用新浪短链接API的方法
2014/11/08 PHP
PHP中两个float(浮点数)比较实例分析
2015/09/27 PHP
PHP call_user_func和call_user_func_array函数的简单理解与应用分析
2019/11/25 PHP
javascript 变量作用域 代码分析
2009/06/26 Javascript
javascript Base类 包含基本的方法
2009/07/22 Javascript
IE与firefox下Dhtml的一些区别小结
2009/12/02 Javascript
JavaScript_object基础入门(必看篇)
2016/06/13 Javascript
Bootstrap 3.x打印预览背景色与文字显示异常的解决
2016/11/06 Javascript
js实现做通讯录的索引滑动显示效果和滑动显示锚点效果
2017/02/18 Javascript
Validform验证时可以为空否则按照指定格式验证
2017/10/20 Javascript
详解ES6 Symbol 的用途
2018/10/14 Javascript
Vue slot用法(小结)
2018/10/22 Javascript
浅谈Javascript常用正则表达式应用
2019/03/08 Javascript
一个小示例告诉你Python语言的优雅之处
2014/07/04 Python
Python实现统计文本文件字数的方法
2017/05/05 Python
Python编程使用NLTK进行自然语言处理详解
2017/11/16 Python
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
Python实现查找最小的k个数示例【两种解法】
2019/01/08 Python
python3实现斐波那契数列(4种方法)
2019/07/15 Python
学python安装的软件总结
2019/10/12 Python
PHP基于phpqrcode类库生成二维码过程解析
2020/05/28 Python
python实现ping命令小程序
2020/12/28 Python
纯CSS3代码实现switch滑动开关按钮效果
2016/08/30 HTML / CSS
HTML5 本地存储实现购物车功能
2017/09/07 HTML / CSS
爱尔兰家电数码商城:Currys PC World爱尔兰
2016/07/23 全球购物
瑞士领先的网上超市:LeShop.ch
2018/11/14 全球购物
珍惜资源的建议书
2014/08/26 职场文书
六查六看剖析材料
2014/10/06 职场文书
机关作风建设剖析材料
2014/10/11 职场文书
开会通知
2015/04/20 职场文书
学术会议领导致辞
2015/07/29 职场文书
创业计划书之闲置物品置换中心
2019/12/25 职场文书
python利用pandas分析学生期末成绩实例代码
2021/07/09 Python