Pyside6实现动画效果
实现目标:实现一个等待动画,在动画展示期间后端进行网络请求。实现所使用组件:QDialog、QLabel、QMovie。
我原本的想法是使用QMovie播放一个等待GIF图,QMovie放置在QLabel中,而QLable放置在QDialog中。在需要展示的时候,使用QDialog.show()进行展示即可。
但是上面的做法会出现问题:使用.show()发现QDialog中的内容根本没有正确展示;但是使用.exec()的时候可以。后面查询有人说是.show()没有进行事件循环。但是使用.exec()会堵塞程序运行,导致网络请求无法继续。
折腾一圈,还是选择了使用多线程实现动画效果
多线程实现动画效果
思路:主线程执行GUI任务,子线程执行网络请求,接收到请求数据后发出完成信号,主线程关闭动画。
因为可能多处都需要进行执行动画效果,并且显示的东西都一样,所以可以使用单例模式实现,还需要实现当完成请求后的关闭动画函数。
def Singleton(cls):
_instance = {}
def _singleton(*args, **kargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kargs)
return _instance[cls]
return _singleton
# 单例模式实现方法有多种
@Singleton
class LoadingGif(QDialog):
def __init__(self):
super().__init__()
self.loadingMovie = QMovie("xxx.gif")
self.label = QLabel(self)
self.label.setMovie(self.loadingMovie)
layout = QVBoxLayout(self)
layout.addWidget(self.label)
self.setLayout(layout)
self.loadingMovie.start()
def afterRequset(self, res):
# 请求完成后的后续处理以及关闭Dialog
...
self.accept()
而网络请求则可以包装成一个QThread类,将发送网络请求的代码写在run函数中,并且添加一个完成信号,如下:
class RequestThread(QThread):
finished = Signal(str)
def __init__(self, requestParam):
super().__init__()
...
def run(self):
# 模拟网络请求
...
self.finished.emit(res)
在主程序中,当需要发送请求并展示动画时,代码如下:
...
loadingGif = LoadingGif() # 获得动画Dialog对象
requestThread = RequestThread(param) # 生成一个网络请求线程对象
requestThread.finished.connect(loadingGif.afterRequset) # 将信号和槽连接
thread.start() # 启动线程,执行网络请求
loadingDlg.exec() # 显示动画,直到请求完成
...
如有错误之处,欢迎指正