详解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冒泡排序算法的实现代码
Nov 21 Python
python查找第k小元素代码分享
Dec 18 Python
在Python3中初学者应会的一些基本的提升效率的小技巧
Mar 31 Python
Python的多态性实例分析
Jul 07 Python
python实现井字棋游戏
Mar 30 Python
Python使用Mechanize模块编写爬虫的要点解析
Mar 31 Python
Python动态参数/命名空间/函数嵌套/global和nonlocal
May 29 Python
python requests抓取one推送文字和图片代码实例
Nov 04 Python
关于Python 常用获取元素 Driver 总结
Nov 24 Python
python 实现&quot;神经衰弱&quot;翻牌游戏
Nov 09 Python
pycharm实现猜数游戏
Dec 07 Python
聊聊基于pytorch实现Resnet对本地数据集的训练问题
Mar 25 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仿ZOL分页类代码
2008/10/02 PHP
PHP小程序自动提交到自助友情连接
2009/11/24 PHP
php mssql扩展SQL查询中文字段名解决方法
2012/10/15 PHP
PHP json_encode中文乱码问题的解决办法
2013/09/09 PHP
ThinkPHP3.1新特性之动态设置自动完成和自动验证示例
2014/06/19 PHP
不错的asp中显示新闻的功能
2006/10/13 Javascript
使用javascript访问XML数据的实例
2006/12/27 Javascript
JSON 教程 json入门学习笔记
2020/09/22 Javascript
纯JS实现旋转图片3D展示效果
2015/04/12 Javascript
JavaScript变量的作用域全解析
2015/08/14 Javascript
jquery通过扩展select控件实现支持enter或focus选择的方法
2015/11/19 Javascript
浅析Javascript的自动分号插入(ASI)机制
2016/09/29 Javascript
Ajax+FormData+javascript实现无刷新表单信息提交
2016/10/24 Javascript
解决vue组件中使用v-for出现告警问题及v for指令介绍
2017/11/11 Javascript
解决nodejs的npm命令无反应的问题
2018/05/17 NodeJs
JS实现点击按钮可实现编辑功能
2018/07/03 Javascript
JS在if中的强制类型转换方式
2018/07/15 Javascript
Vue.js的复用组件开发流程完整记录
2018/11/29 Javascript
Vue分页器实现原理详解
2019/06/28 Javascript
Vue 的双向绑定原理与用法揭秘
2020/05/06 Javascript
Python实现的检测网站挂马程序
2014/11/30 Python
python基础教程项目二之画幅好画
2018/04/02 Python
Python应用库大全总结
2018/05/30 Python
pthon贪吃蛇游戏详细代码
2019/01/27 Python
python生成带有表格的图片实例
2019/02/03 Python
详解Python 函数如何重载?
2019/04/23 Python
python3注册全局热键的实现
2020/03/22 Python
使用HTML5和CSS3表单验证功能
2017/05/05 HTML / CSS
利用HTML5实现使用按钮控制背景音乐开关
2015/09/21 HTML / CSS
教师岗位职责
2013/11/17 职场文书
2014高考励志标语
2014/06/05 职场文书
顶岗实习协议书
2015/01/29 职场文书
三峡导游词
2015/01/31 职场文书
收入证明申请书
2015/06/12 职场文书
小学生禁毒教育心得体会
2016/01/15 职场文书
2016年幼儿园庆六一开幕词
2016/03/04 职场文书