PyQt5显示窗口后运行功能

时间:2017-07-18 19:25:20

标签: python python-3.x pyqt pyqt5

我想在GUI显示后调用一个函数。如果我在 init 中运行函数,它会阻止gui显示,直到它完成。

class MyApp(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.function() #waits for this to finish until gui displayed
    def function(self):
        self.guiBox.setValue(initData)
        #inits stuff, takes 5 seconds

该功能通过串口初始化一台设备......需要几秒钟,它需要gui属性并更新gui显示框。

4 个答案:

答案 0 :(得分:4)

在1毫秒和通话功能后添加单发计时器

  class MyApp(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
      QtWidgets.QMainWindow.__init__(self)
      Ui_MainWindow.__init__(self)
      self.setupUi(self)
      QTimer.singleShot(1,self.function) #waits for this to finish until gui displayed
    def function(self):
      self.guiBox.setValue(initData)
      #inits stuff, takes 5 seconds

答案 1 :(得分:2)

耗时的任务是阻塞的,这违背了在GUI上工作的自然方式,一种选择是使用def function(self): self.guiBox.setValue(initData) code1 QtWidgets.qApp.processEvents() code2 QtWidgets.qApp.processEvents() ... ,例如:

{{1}}

答案 2 :(得分:0)

我会推荐QThreads,特别是如果你在你的"功能中执行大量其他操作。"这个例子不是在PyQt中进行线程化的唯一方法,但是想一个能够在线程和主gui之间来回传递数据的例子是最好的。

import os
import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget
from PyQt5.QtCore import QUrl, QEventLoop, QThread, QObject, pyqtSlot, pyqtSignal
from PyQt5.QtWebEngineWidgets import QWebEngineView

class time_consuming_function(QObject):
    def __init__(self, widget):
        super(time_consuming_function, self).__init__()
        self.widget = widget
        self.run_trigger.connect(self.run)

    run_trigger = pyqtSignal(int, int)
    @pyqtSlot(int, int)
    def run(self, int1, int2):
        print("In Time Consuming Function")
        for i in range(100000000):
            i*i
        print("Finished with Time Consuming Function")
        self.widget.someTrigger.emit([1, 2, 3])

class WebPage(QWebEngineView):
    def __init__(self):
        QWebEngineView.__init__(self)
        self.load(QUrl("https://www.google.com"))
        self.loadFinished.connect(self._on_load_finished)

        self.someTrigger.connect(self.gui_response)

        self.thread = QThread()
        self.thread.start()
        self.consume = time_consuming_function(self)
        self.consume.moveToThread(self.thread)
        self.consume.run_trigger.emit(1,1)

    someTrigger = pyqtSignal(list)

    def _on_load_finished(self):
        print("Finished Loading")

    def gui_response(self, data):
        print("Responding to GUI: ", str(data))



if __name__ == "__main__":
    app = QApplication(sys.argv)
    web = WebPage()
    web.show()
    sys.exit(app.exec_())  

答案 3 :(得分:0)

我会说没有使用线程和相关的最简单的方法是验证是否执行了显示窗口的最后一个事件,然后调用你的方法。

你会有类似的东西:

import sys

from PyQt5.QtCore import QEvent
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow


class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.setFixedSize(500, 500)
        self.move(300, 50)

    def print_1_bi(self):
        for i in range(10**9): print(i)

    def event(self, event):
        if event.type() == QEvent.InputMethodQuery:
            self.print_1_bi()
        return super(MainWindow, self).event(event)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

注意: 请记住,即使UI已经显示您的应用程序将等待您的方法完成,如果这是一个问题,您将不得不使用过程,就像那些人告诉你的在其他答案中。