自己做了一个tcp工具,在学习动画的时候踩了坑,需求是根据上线变绿色,离线变灰色,如果连接断开了,则变为灰色

问题现象:

可以看到点击“连接”,“离线”的时候动画是正常的,但是当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 == "":
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线程中无法运行问题的更多相关文章

  1. 通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。

    Web Workers API - Web API 接口参考 | MDNhttps://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API ...

  2. 重点:怎样正确的使用QThread类(很多详细例子的对比,注意:QThread 中所有实现的函数是被创建它的线程来调用的,不是在线程中)good

    背景描述: 以前,继承 QThread 重新实现 run() 函数是使用 QThread唯一推荐的使用方法.这是相当直观和易于使用的.但是在工作线程中使用槽机制和Qt事件循环时,一些用户使用错了.Qt ...

  3. 在不开启事件循环的线程中使用QTimer(QThread::run函数自带事件循环,在构造函数里创建线程,是一种很有意思的线程用法) good

    引入 QTimer是Qt自带的定时器类,QTimer运行时是依赖于事件循环的,简单来说,在一个不开启事件循环(未调用exec() )的线程中,QTimer是无法使用的.通过分析Qt源码可发现,调用QT ...

  4. Android的post()方法究竟运行在哪个线程中

    Android中我们常用的post()方法大致有两种情况: 1.如果post方法是handler的,则Runnable执行在handler依附线程中,可能是主线程,也可能是其他线程 2.如果post方 ...

  5. 让NSURLConnection在子线程中运行

    可以有两个办法让NSURLConnection在子线程中运行,即将NSURLConnection加入到run loop或者NSOperationQueue中去运行. 前面提到可以将NSTimer手动加 ...

  6. iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行

    可以有两个办法让NSURLConnection在子线程中运行,即将NSURLConnection加入到run loop或者NSOperationQueue中去运行. 前面提到可以将NSTimer手动加 ...

  7. 获取Java VM中当前运行的所有线程

    /** * 获取Java VM中当前运行的所有线程 * @return */ public static Thread[] findAllThreads() { ThreadGroup group = ...

  8. Erlang运行时中的无锁队列及其在异步线程中的应用

    本文首先介绍 Erlang 运行时中需要使用无锁队列的场合,然后介绍无锁队列的基本原理及会遇到的问题,接下来介绍 Erlang 运行时中如何通过“线程进度”机制解决无锁队列的问题,并介绍 Erlang ...

  9. [Swift实际操作]八、实用进阶-(3)闭包在定时任务、动画和线程中的使用实际操作

    闭包的使用相当广泛,它是可以在代码中被传递和引用的具有独立功能的模块.双击打开之前创建的空白项目.本文将演示闭包在定时任务.动画和线程中的使用.在左侧的项目导航区,打开视图控制器的代码文件:ViewC ...

随机推荐

  1. tomcat集群的failover机制

    集群要提供高可用性就必须要有某种机制去保证,常用的机制为failover(故障转移),简单说就是通过一定的heartbeat检测是否有故障,一旦故障发生备份节点则接管故障节点的工作. tomcat使用 ...

  2. Portlet开发入门实例

    1原生Portlet开发 这是最简单.最本质的开发方式,直接基于Portlet规范定义的接口开发Portlet.优点是贴近底层比较灵活, 缺点当然就是所有事情都要自己去做.就好比不用SpringMVC ...

  3. UNIX网络编程——非阻塞connect

    当在一个非阻塞的TCP套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的TCP三次握手继续进行.我们接着使用select检测这个连接或成功或失败的已建 ...

  4. UNIX网络编程——UDP回射服务器程序(初级版本)以及漏洞分析

    该函数提供的是一个迭代服务器,而不是像TCP服务器那样可以提供一个并发服务器.其中没有对fork的调用,因此单个服务器进程就得处理所有客户.一般来说,大多数TCP服务器是并发的,而大多数UDP服务器是 ...

  5. Handler,MessageQueue Loop 和Message的原理解析

    先介绍和handler一起工作的几个组件 Handler的方法介绍 代码示例 package liu.peng.weather; import java.util.Timer; import java ...

  6. 编译Android 4.4.2源码

    在之前的文章中,和大家分享了在天朝下下载android 4.4.2源码的过程(详见下载android4.4.2源码全过程(附已下载的源码)),现在写下编译的笔记. 虽然在android doc中,有提 ...

  7. 有关Spring注解@xxx的零碎知识

     在Java的Spring开发中经常使用一些注解,例如 @XXX 等等,在网上看到收集整理碎片知识,便于懒人计划^=^... 过去,Spring使用的Java Bean对象必须在配置文件[一般为a ...

  8. Linux的文件系统及其硬盘分区挂载原理

    如果您是一位新手,也许 您还不知道如何把文件从Windows拷贝到Linux上吧?下面,我们将说明Unix文件系统以及mount的工作过程,然后再比较详细地讨论. mount的使用和有关选项.如果您已 ...

  9. XBMC源代码简析 5:视频播放器(dvdplayer)-解复用器(以ffmpeg为例)

    XBMC分析系列文章: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 XBMC源代码分析 4: ...

  10. java程序的加载过程

    昨天笔试阿里有个求java程序加载过程的题目很是复杂,回来研究了好久才有点明白,整理一下.原题代码如下,判断输出: public class StaticTest { public static in ...