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()	# 显示动画,直到请求完成
...

如有错误之处,欢迎指正

posted @ 2024-02-28 16:32  凡璞  阅读(450)  评论(0编辑  收藏  举报
1 2
3 4
5 6