Python+;QT:如何制作非GUI阻塞加载屏幕?

Python+;QT:如何制作非GUI阻塞加载屏幕?,python,qt,pyqt,pyside,Python,Qt,Pyqt,Pyside,PySide新手,因此可能在这里误解了基本原理 我正在编写一个GUI应用程序,它将启动,然后执行各种系统检查: 检查硬件是否存在 检查网络连接 检查API连接 在整个过程中,它将通知用户它当前正在做什么,以及结果 完成检查(并通过)后,它们将进入程序初始屏幕 目前,我一直在尝试使用计时器中的QApplication.processEvents运行检查: if __name__ == '__main__': app = QApplication(sys.argv) rebadg

PySide新手,因此可能在这里误解了基本原理

我正在编写一个GUI应用程序,它将启动,然后执行各种系统检查:

  • 检查硬件是否存在
  • 检查网络连接
  • 检查API连接
在整个过程中,它将通知用户它当前正在做什么,以及结果

完成检查(并通过)后,它们将进入程序初始屏幕

目前,我一直在尝试使用计时器中的
QApplication.processEvents
运行检查:

if __name__ == '__main__':
    app = QApplication(sys.argv)
    rebadger = rebadger()
    rebadger.initUI()
    rebadger.show()

    tT = QTimer()
    tT.setSingleShot(False)
    tT.timeout.connect(QApplication.processEvents)
    tT.start(1000)

    rebadger.rebadgeObj.runChecks()

    sys.exit(app.exec_())
但在检查完成之前,一切都会阻塞

我已经阅读了
QThread
文档,但是我发现很难理解事件逻辑(来自严格的PHP背景)


如果您能帮助您勾勒出如何实现这一目标的框架,我们将不胜感激。

也许您需要的是
QSplashScreen

if __name__ == '__main__':                                                                       

    import time                                                                                  
    app = QtGui.QApplication(sys.argv)                                                           
    splash = QtGui.QSplashScreen(QtGui.QPixmap('splash.png'))                                    
    splash.show()                                                                                
    for n in ("HW presence", "net connectivity", "API connectivity"):                            
        splash.showMessage("Check for {0}".format(n))                                            
        time.sleep(1)                                                                            
        app.processEvents()                                                                      
    mainWin = MainWindow()                                                                       
    splash.finish(mainWin)                                                                       
    mainWin.show()                                                                               
    sys.exit(app.exec_())                                                                        

这是一个示例,说明了如何做您想做的事情,检查长时间运行的后台处理是否使用
QThread
s,作为一个额外功能,您将拥有一个响应性gui,使其适用于任何窗口,而不仅仅是启动屏幕:

from PyQt4 import QtCore as core, QtGui as gui
import time

class MyProccess(core.QThread):

    newProgress = core.pyqtSignal(str)

    def __init__(self,i):
        super(MyProccess,self).__init__()
        self.id = i

    def run(self):
        for j in range(10):
            self.newProgress.emit('task %d at %d%%' % (self.id,j*10))
            time.sleep(0.2)            


class MySplash(gui.QSplashScreen):

    def __init__(self,mw):
        super(MySplash,self).__init__()
        layout = gui.QVBoxLayout(self)
        self.setLayout(layout)
        self.text = gui.QLabel(self)
        layout.addWidget(self.text) 
        self.setGeometry(300,300,100,0)          

        self.task1 = MyProccess(1)
        self.task2 = MyProccess(2)
        self.task3 = MyProccess(3)

        self.task1.newProgress.connect(self.showProgress)
        self.task2.newProgress.connect(self.showProgress)
        self.task3.newProgress.connect(self.showProgress)

        self.task1.finished.connect(self.task2.start)
        self.task2.finished.connect(self.task3.start)
        self.task3.finished.connect(mw.show)
        self.task3.finished.connect(self.hide)

    @core.pyqtSlot(str)
    def showProgress(self,msg):
        self.text.setText(msg)

    def event(self,ev):
        if type(ev) == gui.QShowEvent:
            self.task1.start()
        return super(MySplash,self).event(ev)

app = gui.QApplication([])

mw = gui.QMainWindow()

cw = gui.QWidget()
l = gui.QHBoxLayout()
cw.setLayout(l)
welcome = gui.QLabel()
welcome.setText('Welcome back!')
l.addWidget(welcome)

mw.setCentralWidget(cw)
mw.setGeometry(200,200,300,300)


w = MySplash(mw)
w.show()

app.exec_()

您好TNT-谢谢您的回复。我曾使用/尝试使用SplashScreen,但发现它不适合我想要的(即,设计仅限于一个简单的图像,点击后关闭,当然,仍然需要processEvents()并不能解决问题)理论上,如果splashScreen需要,它也可以用于任何其他常规形式?事实上,例如,在
mainWin
中,您可以使用状态栏进行输出。但还需要
processEvents()
。但是如果for循环中的任务需要很长的时间来处理,GUI仍然会阻塞。这很完美:进程从线程发回,线程是渐进的/有序的,GUI不会被阻塞,之后生命可以继续。你能解释一下@core.pyqtSlot(str)吗请稍微引用?
MyProcess
包含对标签(
self.out
)的未使用引用,可能会尝试使用其setText()方法。据我所知,这是不应该做的,所以这个变量没有意义。@TNT是的,你是对的,但我不使用它,也许它是我的答案的早期版本,我直到现在才意识到;)thanks@swxdecorator
@core.pyqtSlot
用于将方法标记为PyQt中的插槽(在我的代码中,这不是绝对必要的,但这是一个很好的编程实践)如果你想学习如何/为什么使用,你应该阅读,希望它能有所帮助。