Pyqt5等到窗口小部件可见

时间:2017-06-16 15:45:55

标签: python pyqt pyqt5 python-3.6

我正在寻找一种方法,在调用函数之前等待QWidget完全显示。我有两个窗口:父母和孩子。

父窗体是一个窗口,其中有一个调用openChild的按钮,该按钮隐藏父级,显示子级,然后执行子级的主要功能busyFunc

from PyQt5 import QtCore, QtGui, QtWidgets
from Child import Child_Form
import sys

class Parent_Form(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.setupUi(self)
        self.Child = Child_Form(self)

    def setupUi(self, Parent):
        Parent.setObjectName("Parent")
        Parent.resize(400, 300)
        self.nextWindow = QtWidgets.QPushButton(Parent)
        self.nextWindow.setGeometry(QtCore.QRect(150, 120, 91, 31))
        self.nextWindow.setObjectName("nextWindow")

        self.retranslateUi(Parent)
        QtCore.QMetaObject.connectSlotsByName(Parent)

    def retranslateUi(self, Parent):
        _translate = QtCore.QCoreApplication.translate
        Parent.setWindowTitle(_translate("Parent", "Parent Window"))
        self.nextWindow.setText(_translate("Parent", "Next Window"))

        self.nextWindow.clicked.connect(self.openChild)

    def openChild(self):
        self.hide()
        self.Child.show()
        self.Child.busyFunc()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = Parent_Form()
    ex.show()
    sys.exit(app.exec_())

子表单只有一个标签和一个带有文本编辑的滚动区域。

from PyQt5 import QtCore, QtGui, QtWidgets

class Child_Form(QtWidgets.QWidget):
    def __init__(self, Parent_Form):
        QtWidgets.QWidget.__init__(self)
        self.setupUi(self)
        self.parent = Parent_Form

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(20, 10, 61, 16))
        self.label.setObjectName("label")
        self.scrollArea = QtWidgets.QScrollArea(Form)
        self.scrollArea.setGeometry(QtCore.QRect(20, 40, 361, 241))
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 359, 239))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.textEdit = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
        self.textEdit.setGeometry(QtCore.QRect(0, 0, 361, 241))
        self.textEdit.setObjectName("textEdit")
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Child Window"))
        self.label.setText(_translate("Form", "Status:"))

    def busyFunc(self):
        for i in range(0, 1000000000):
            pass

问题是调用busyFunc时(实际功能是一个庞大的程序,所以我为了清楚起见省略了它。我使用循环模拟问题)。

父隐藏,但在busyFunc完成之前,Child看起来像这样。

如何完全像这样加载子项然后执行busyFunc

1 个答案:

答案 0 :(得分:1)

一种解决方案是在一段时间后通过计时器启动busyFunc函数。

def openChild(self):
    self.hide()
    self.Child.show()
    QtCore.QTimer.singleShot(100, self.Child.busyFunc)

问题是在运行此函数时阻塞了接口,为了解决这个问题,建议在线程上运行该任务

class Thread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def run(self):
        for i in range(0, 1000000000):
            pass

class Child_Form(QtWidgets.QWidget):
    def __init__(self, Parent_Form):
        [...]
    def busyFunc(self):
        self.thread = Thread(self)
        self.thread.start() 

显然由于busyFunc的当前代码不与GUI交互,即不更新GUI的任何值,所以没有问题,但如果这个必须更新GUI的一些数据,它必须通过信号,不直接:

class Thread(QtCore.QThread):
    signal = QtCore.pyqtSignal(str)
    signal2 = QtCore.pyqtSignal(list)
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def run(self):
        self.signal.emit("start")
        for i in range(0, 1000000000):
            pass
        self.signal.emit("finish")
        self.signal2.emit([1, 2, 3, 4])

class Child_Form(QtWidgets.QWidget):
    def __init__(self, Parent_Form):
        [...]
    def busyFunc(self):
        self.thread = Thread(self)
        self.thread.signal.connect(lambda text: self.textEdit.append(text))
        self.thread.signal2.connect(lambda l: print(l))
        self.thread.start() 

class Parent_Form(QtWidgets.QWidget):
    def __init__(self):
        [...]
    def openChild(self):
        self.hide()
        self.Child.show()
        self.Child.busyFunc()