PyQt5:直到执行while循环时才会显示子窗口

时间:2018-11-21 04:25:01

标签: python pyqt5

我有一个主类,该类显示带有按钮的窗口。单击按钮后,将调用一个子类(包含while循环),该子类在单独的窗口中显示“是”。我不确定执行while循环后为什么会显示子窗口。随附的代码供您参考。非常感谢您的帮助。

class test1(QtWidgets.QMainWindow):

    def __init__(self):
        super (test1, self).__init__()
        test1.setGeometry(self, 20, 20, 400, 250)

        btn = QtWidgets.QPushButton("Add", self)
        btn.clicked.connect(self.Check)    
        btn.resize(btn.sizeHint())
        btn.move(10, 170)   
        self.show()

    def Check(self):
        self.test2=test2()



class test2(QtWidgets.QMainWindow):

    def __init__(self):
        super (test2, self).__init__()

        test2.setGeometry(self,20, 20, 450, 100)
        self.label = QtWidgets.QLabel("Yay",self)
        self.show()
        a=50
        b=60
        x=True
        time.sleep(5)
        while (x):
            if a!=b:
                a+=1
            else:
                x=False
def run():
    app = QtWidgets.QApplication(sys.argv)
    GUI = test1()
    GUI.show()
    sys.exit(app.exec_())

run()

1 个答案:

答案 0 :(得分:0)

GUI驻留在事件循环中,该循环允许获取键盘,鼠标,逻辑等各种元素的数据并更新GUI的状态,因此如果GUI被冻结,不会允许其正常工作。在这种情况下,阻塞事件循环的是睡眠,而while不会干预,因为它的执行时间不到1毫秒。

因此,占用大量时间的任务必须在GUI的不同线程中执行,以避免被阻塞,但是在您这种情况下,可以用QTimer代替睡眠。

总而言之,睡眠使GUI冻结了。我看到该代码具有教育意义,因此我将向您展示几个选项:

threading.Thread():

import threading

# ...

class test2(QtWidgets.QMainWindow):
    def __init__(self):
        super (test2, self).__init__()
        test2.setGeometry(self,20, 20, 450, 100)
        self.label = QtWidgets.QLabel("Yay",self)
        self.show()

        threading.Thread(target=self.foo, daemon=True).start()

    def foo(self):
        time.sleep(5)
        a=50
        b=60
        x=True
        while x:
            if a != b:
                a += 1
                print(a)
            else:
                x = False

QTimer + QEventLoop:

class test2(QtWidgets.QMainWindow):
    def __init__(self):
        super (test2, self).__init__()
        test2.setGeometry(self,20, 20, 450, 100)
        self.label = QtWidgets.QLabel("Yay",self)
        self.show()
        loop = QtCore.QEventLoop()
        QtCore.QTimer.singleShot(5*1000, loop.quit)
        loop.exec_()
        a=50
        b=60
        x=True
        while x:
            if a != b:
                a += 1
                print(a)
            else:
                x = False

QTimer:

class test2(QtWidgets.QMainWindow):
    def __init__(self):
        super (test2, self).__init__()
        test2.setGeometry(self,20, 20, 450, 100)
        self.label = QtWidgets.QLabel("Yay",self)
        self.show()
        QtCore.QTimer.singleShot(5*1000, self.foo)

    def foo(self):
        a=50
        b=60
        x=True
        while x:
            if a != b:
                a += 1
                print(a)
            else:
                x = False

作为一般结论,如果建议的时间大于建议在另一个线程中执行的时间,则在GUI线程中执行的任务应少于30ms。在循环中的每个任务都满足上述要求但又有很多迭代的情况下,可以使用QTimer定期执行循环中的任务。