简体   繁体   English

PyQt5 显示窗口后运行函数

[英]PyQt5 Run function after displaying window

I would like to call a function after the GUI displays.我想在 GUI 显示后调用一个函数。 If I run function in init it prevents gui from displaying until after it is completed.如果我在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

The function initializes a piece of equipment via serial port... It takes s few seconds, and it takes gui attributes and updates gui display boxes.该函数通过串口初始化一个设备...它需要几秒钟,它需要gui属性并更新gui显示框。

Add single shot timer 1 ms and after call function添加单次定时器 1 ms 和调用后功能

  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

Time-consuming tasks are blocking, and this goes against the natural way of working on the GUI, an option is to use qApp.processEvents() , for example:耗时的任务被阻塞,这违背了在 GUI 上工作的自然方式,一个选项是使用qApp.processEvents() ,例如:

def function(self):
    self.guiBox.setValue(initData)
    code1
    QtWidgets.qApp.processEvents()
    code2
    QtWidgets.qApp.processEvents()
    ...

I would recommend QThreads, especially if you are performing a ton of other actions in your "function."我会推荐 QThreads,尤其是当您在“函数”中执行大量其他操作时。 This example isn't the only way to thread in PyQt, but thought an example where you are able to pass data back and forth between the thread and the main gui would be best.这个例子不是在 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_())  

I'd say the easiest way without using thread and related would be to verify if the last event of showing up the window was executed and then call your method.我会说不使用线程和相关的最简单方法是验证显示窗口的最后一个事件是否已执行,然后调用您的方法。


You'd have something like that:你会有这样的事情:

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_())

Note: Remember that even though the UI already showed up your application will be waiting your method to finish, if it's a problem you'll have to use process like the guys told you to in the other answers.注意:请记住,即使 UI 已经出现,您的应用程序也会等待您的方法完成,如果这是一个问题,您将不得不像其他答案中的人告诉您的那样使用流程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM