开发者小伙伴们!我有一个关于 Qt 和多线程的问题。
=== 简短版 ============================================
Qt可以做我想做的事吗?即(1)显示装载机;(2)在后台下载一个gif;(3) 下载后的gif在主窗口显示?
=== 长版 ==============================================
我有这样的想法,当我按下按钮时,它:
- 显示装载机;
- 激活从网络下载 gif 的线程;
- 用下载的替换隐藏在主窗口中的默认gif并显示它
- 隐藏装载机;
我遇到的问题是,当下载的 gif 被显示时,它被“冻结”或者只显示第一帧。除此之外一切都很好。但是,它需要在加载器隐藏后动画化。
这里提到_
因此,Qt 事件循环负责执行您的代码以响应您程序中发生的各种事情,但是当它执行您的代码时,它不能做任何其他事情。
我相信这是问题的核心。还建议
建议将 QThread 与 Qt 一起使用,而不是 Python 线程,但是如果您不需要从函数与主线程进行通信,Python 线程将可以正常工作。
由于我的线程替换了默认 gif 的内容,我相信它确实会返回:(
请在下面找到我的代码:)
import sys
from time import sleep
from PyQt5.QtCore import QThread
from PyQt5.QtGui import QMovie
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel
class ChangeGif(QThread):
"""
A worker that:
1 - waits for 1 second;
2 - changes the content of the default gif;
3 - shows the default gif with new contents and hide the loader.
"""
def __init__(self, all_widgets):
QThread.__init__(self)
self.all = all_widgets
def run(self):
sleep(1)
self.new_gif_file = QMovie("files/new.gif") # This is the "right" gif that freezes :(
self.new_gif_file.start()
self.all.gif_label.setMovie(self.new_gif_file)
self.all.gif_label.show()
self.all.loader_label.hide()
class MainWindow(QWidget):
"""
Main window that shows a button. If you push the button, the following happens:
1 - a loader is shown;
2 - a thread in background is started;
3 - the thread changes the contents of the default gif;
4 - when the gif is replaced, the loader disappears and the default gif with the new content is shown
"""
def __init__(self):
super(MainWindow, self).__init__()
# BUTTON
self.button = QPushButton("Push me", self)
self.button.setFixedSize(100, 50)
self.button.clicked.connect(lambda: self.change_gif())
# DEFAULT GIF
self.gif_file = QMovie("files/default.gif") # This is the "wrong" gif
self.gif_file.start()
self.gif_label = QLabel(self)
self.gif_label.setMovie(self.gif_file)
self.gif_label.move(self.button.width(), 0)
self.gif_label.hide()
# LOADER
self.loader_file = QMovie("files/loader.gif")
self.loader_file.start()
self.loader_label = QLabel(self)
self.loader_label.setMovie(self.loader_file)
self.loader_label.move(self.button.width(), 0)
self.loader_label.hide()
# WINDOW SETTINGS
self.setFixedSize(500, 500)
self.show()
def change_gif(self):
self.loader_label.show()
self.worker = ChangeGif(self)
self.worker.start()
app = QApplication(sys.argv)
window = MainWindow()
app.exec_()