python - 为什么我的加载屏幕没有使用 QThread 显示?
问题描述
我正在制作一个桌面应用程序,一旦加载数据库,我想显示一个加载屏幕。一个简单的搜索让我在 QLabel 中使用带有 QThread 对象的 gif 文件。但就我而言,QThread 不会显示任何内容。该线程工作正常,但我的实现有问题,我无法弄清楚是什么。我的示例代码如下:
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QDialog, QApplication, QPushButton
from PyQt5.QtCore import QThread
from PyQt5.QtGui import QMovie
import sys
import time
class myThread(QThread):
def run(self):
test = QWidget() # Only creating this to give parent to QDialog and QLabel objects in upcoming lines
dialog = QDialog(test)
vbox = QVBoxLayout()
lbl = QLabel(test)
self.moviee = QMovie('Loading.gif')
lbl.setMovie(self.moviee)
self.moviee.start()
vbox.addWidget(lbl)
dialog.setLayout(vbox)
dialog.show()
def stop(self):
self.moviee.stop()
class Main(QWidget):
def __init__(self):
super().__init__()
print('Thread is to be called here...')
thread = myThread()
thread.run()
print('Thread has been called...')
btn= QPushButton('Test button')
vbox = QVBoxLayout()
vbox.addWidget(btn)
self.setLayout(vbox)
time.sleep(5) # sleep function used to emulate funcitons in actual program
# thread.stop()
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Main()
sys.exit(app.exec_())
带有QMovie
对象的代码块在Main
循环中时工作正常,所以我的QThread
.
解决方案
您的代码有几个问题。正如@musicamante 所说,您不能在主线程之外创建小部件。这意味着您无法在myThread.run
. 相反,您可以将对话框的管理移至Main
并使用插槽和信号来打开和关闭对话框。
其次,所有像你这样耗时的任务time.sleep(5)
都应该放在myThread.run
.
考虑到这一点,你可以做这样的事情
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QDialog, QApplication, QPushButton
from PyQt5.QtCore import QThread
from PyQt5.QtGui import QMovie
import sys
import time
class myThread(QThread):
def run(self):
# time consuming actions
time.sleep(5)
class Main(QWidget):
def __init__(self):
super().__init__()
print('Thread is to be called here...')
self.load()
print('Thread has been called...')
btn= QPushButton('Test button')
vbox = QVBoxLayout()
vbox.addWidget(btn)
self.setLayout(vbox)
self.show()
def load(self):
# setup dialog
dialog = QDialog(self)
vbox = QVBoxLayout()
lbl = QLabel(self)
self.moviee = QMovie('Loading.gif')
lbl.setMovie(self.moviee)
self.moviee.start()
vbox.addWidget(lbl)
dialog.setLayout(vbox)
# setup thread
thread = myThread()
thread.finished.connect(thread.deleteLater)
thread.finished.connect(dialog.close)
thread.finished.connect(dialog.deleteLater)
thread.start()
dialog.exec()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Main()
app.exec()
推荐阅读
- php - 如何在 Laravel 中实现自定义频道通知
- mariadb - 在联机服务器上工作时如何使用外键
- chapel - 如何将 Chapel 字符串传递给需要(非常量)char* 的 C 函数?
- regex - 表单输入模式和全名验证
- javascript - 在 react-admin 上为多个资源设置全局过滤器的最佳方法是什么?
- python - 在无法访问库源的情况下使用 swig c++ 到 python
- c# - 获取 DbContext Entity Framework Core 2.1 中的实体模型列表
- perl - 处理@ARGS 的两个警告
- c# - 根据定义的间隔将开始和结束时间戳分成两部分
- python - 如何改进这些关于在 Python 中随机划分学生组的代码