详解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分割TXT文件成4K的TXT文件
May 23 Python
Python实现抓取页面上链接的简单爬虫分享
Jan 21 Python
Python实现并行抓取整站40万条房价数据(可更换抓取城市)
Dec 14 Python
Python创建xml文件示例
Mar 22 Python
用python编写第一个IDA插件的实例
May 29 Python
Python开发虚拟环境使用virtualenvwrapper的搭建步骤教程图解
Sep 19 Python
Python3爬虫学习之MySQL数据库存储爬取的信息详解
Dec 12 Python
python分数表示方式和写法
Jun 26 Python
关于PyTorch 自动求导机制详解
Aug 18 Python
pytorch下使用LSTM神经网络写诗实例
Jan 14 Python
python实现FTP文件传输的方法(服务器端和客户端)
Mar 20 Python
解决Jupyter NoteBook输出的图表太小看不清问题
Apr 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中urlencode与rawurlencode的区别
2016/09/05 PHP
jQuery弹性滑动导航菜单实现思路及代码
2013/05/02 Javascript
js改变鼠标的形状和样式的方法
2014/03/31 Javascript
浅谈JSON.parse()和JSON.stringify()
2015/07/14 Javascript
JavaScript事件学习小结(三)js事件对象
2016/06/09 Javascript
canvas 实现中国象棋
2017/02/17 Javascript
微信小程序实现表单校验功能
2020/03/30 Javascript
p5.js入门教程和基本形状绘制
2018/03/15 Javascript
Vue resource三种请求格式和万能测试地址
2018/09/26 Javascript
element form 校验数组每一项实例代码
2019/10/10 Javascript
vue中实现点击按钮滚动到页面对应位置的方法(使用c3平滑属性实现)
2019/12/29 Javascript
详解vue-template-admin三级路由无法缓存的解决方案
2020/03/10 Javascript
nodejs+koa2 实现模仿springMVC框架
2020/10/21 NodeJs
node.js如何操作MySQL数据库
2020/10/29 Javascript
jQuery列表动态增加和删除的实现方法
2020/11/05 jQuery
[01:17:55]VGJ.T vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/20 DOTA
[46:55]完美世界DOTA2联赛决赛 FTD vs Phoenix 第三场 11.08
2020/11/11 DOTA
查看Python安装路径以及安装包路径小技巧
2015/04/28 Python
python使用wxpython开发简单记事本的方法
2015/05/20 Python
Python 中 Meta Classes详解
2016/02/13 Python
python 递归遍历文件夹,并打印满足条件的文件路径实例
2017/08/30 Python
Python及PyCharm下载与安装教程
2017/11/18 Python
Python学习笔记之open()函数打开文件路径报错问题
2018/04/28 Python
Python 经典面试题 21 道【不可错过】
2018/09/21 Python
Django设置Postgresql的操作
2020/05/14 Python
Django bulk_create()、update()与数据库事务的效率对比分析
2020/05/15 Python
pyecharts调整图例与各板块的位置间距实例
2020/05/16 Python
Python新手学习函数默认参数设置
2020/06/03 Python
浅谈Python中的生成器和迭代器
2020/06/19 Python
python爬虫要用到的库总结
2020/07/28 Python
HTML5 直播疯狂点赞动画实现代码 附源码
2020/04/14 HTML / CSS
美国时尚配饰品牌:Dooney & Bourke
2017/11/14 全球购物
英国名牌男装店:Standout
2021/02/17 全球购物
热情服务标语
2014/10/07 职场文书
2016年国庆节新闻稿范文
2015/11/25 职场文书
Windows中Redis安装配置流程并实现远程访问功能
2021/06/07 Redis