自己做了一个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. 【Android应用开发】Android Studio 错误集锦 -- 将所有的 AS 错误集合到本文

    . 一. 编译错误 1. "AndroidManifest.xml file not found" 错误 (1) 报错信息 报错信息 : -- Message Make : Inf ...

  2. Android优化之ArrayMap

    ArrayMap的介绍 官方对ArrayMap也有说明:它不是一个适应大数据的数据结构,相比传统的HashMap速度要慢,因为查找方法是二分法,并且当你删除或者添加数据时,会对空间重新调整,在使用大量 ...

  3. [Mysql]备份同库中一张表的历史记录 insert into ..select

    需求 现在有个这么一个需求,mysql中有个表,数据增长的很快,但是呢这个数据有效期也就是1个月,一个月以前的记录不太重要了,但是又不能删除.为了保证这个表的查询速度,需要一个简单的备份表,把数据倒进 ...

  4. 【shell脚本】nginx每天自动切割日志脚本

    nginx每天日志量比较大的时候,最好每天自动切割,存储,这样可以方面以后的查询和分析 #!/bin/sh ################### #filename: nginx_log_rotat ...

  5. UNIX环境高级编程——进程关系

    一.终端的概念 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal),控制终端是保存在PCB中的信息,而我们 ...

  6. (二)php的常量和变量

    [php在命令行下接收参数] 如果在命令行调试php,传入的参数通过$argv获取,注意其中包含了文件名这一个元素,数组中元素的个数通过$argc获取. [可变变量] 指的是变量的名称可变,变量的标识 ...

  7. 【一天一道LeetCode】#80. Remove Duplicates from Sorted Array II

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Follow ...

  8. 3、使用Gradle创建Libgdx项目

    (原文链接:http://www.libgdx.cn/topic/20/3-%E4%BD%BF%E7%94%A8gradle%E5%88%9B%E5%BB%BAlibgdx%E9%A1%B9%E7%9 ...

  9. android报错 Expected BEGIN_OBJECT but was STRING at line 1 column 39 path $

    我在使用retrofit和Gson配合时,出现了这个问题,疑惑中乱七八糟瞎搞了一个下午没有解决.期间怀疑Gson解析不能使用泛型(因为我的解析使用了泛型),后来又觉得可能是我的关键字正好是解析器的某个 ...

  10. 不要使用jQuery触发原生事件

    原文链接: DO NOT TRIGGER REAL EVENT NAMES WITH JQUERY! 原文日期: 2014年02月26日 翻译日期: 2014年03月2日 翻译人员: 铁锚 JavaS ...