详解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中ConfigParse模块的用法
Sep 29 Python
Python cookbook(数据结构与算法)筛选及提取序列中元素的方法
Mar 19 Python
python 拷贝特定后缀名文件,并保留原始目录结构的实例
Apr 27 Python
PyCharm安装第三方库如Requests的图文教程
May 18 Python
selenium设置proxy、headers的方法(phantomjs、Chrome、Firefox)
Nov 29 Python
Python实现的拉格朗日插值法示例
Jan 08 Python
Python 多个图同时在不同窗口显示的实现方法
Jul 07 Python
python使用原始套接字发送二层包(链路层帧)的方法
Jul 22 Python
使用Python实现分别输出每个数组
Dec 06 Python
python如何通过pyqt5实现进度条
Jan 20 Python
Python数组拼接np.concatenate实现过程
Apr 18 Python
python 用opencv实现图像修复和图像金字塔
Nov 27 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 和 MySQL 时区的一点总结
2008/03/26 PHP
PHP编程求最大公约数与最小公倍数的方法示例
2017/05/29 PHP
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
基于jQuery实现文本框缩放以及上下移动功能
2014/11/24 Javascript
21个JavaScript事件(Events)属性汇总
2014/12/02 Javascript
Angularjs基础知识及示例汇总
2015/01/22 Javascript
node.js require() 源码解读
2015/12/13 Javascript
深入浅析JavaScript函数前面的加号和叹号
2016/07/09 Javascript
JS对HTML表格进行增删改操作
2016/08/22 Javascript
利用BootStrap的Carousel.js实现轮播图动画效果
2016/12/21 Javascript
JS获取多维数组中相同键的值实现方法示例
2017/01/06 Javascript
Vue 重置组件到初始状态的方法示例
2018/10/10 Javascript
如何自动化部署项目?折腾服务器之旅~
2019/04/16 Javascript
详解微信小程序文件下载--视频和图片
2019/04/24 Javascript
微信小程序图表插件wx-charts用法实例详解
2019/05/20 Javascript
TypeScript类型声明书写详解
2019/08/28 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
2020/03/05 Javascript
有趣的JavaScript隐式类型转换操作实例分析
2020/05/02 Javascript
H5 js点击按钮复制文本到粘贴板
2020/11/19 Javascript
[01:41]DOTA2超级联赛专访YYF 称一辈子难忘TI2
2013/05/28 DOTA
[42:20]2014 DOTA2华西杯精英邀请赛5 24 DK VS NewBee
2014/05/25 DOTA
pymongo实现控制mongodb中数字字段做加法的方法
2015/03/26 Python
python连接远程ftp服务器并列出目录下文件的方法
2015/04/01 Python
Python Socket实现简单TCP Server/client功能示例
2017/08/05 Python
Linux CentOS7下安装python3 的方法
2018/01/21 Python
python实现百度语音识别api
2018/04/10 Python
Django中如何防范CSRF跨站点请求伪造攻击的实现
2019/04/28 Python
PyTorch的torch.cat用法
2020/06/28 Python
python实现经典排序算法的示例代码
2021/02/07 Python
测试时代收集的软件测试面试题
2013/09/25 面试题
出纳岗位职责
2013/11/09 职场文书
美术学专业求职信
2014/07/23 职场文书
2015年度班主任自我评价
2015/03/11 职场文书
餐厅服务员管理制度
2015/08/05 职场文书
小学生红领巾广播稿
2015/08/19 职场文书
想创业成功,需要掌握这些要点
2019/12/06 职场文书