使用 PyQt5,实现两个窗口自动永远循环

Posted

技术标签:

【中文标题】使用 PyQt5,实现两个窗口自动永远循环【英文标题】:With PyQt5, implement two windows looping forever automatically 【发布时间】:2021-03-27 20:17:44 【问题描述】:

使用 PyQt5,我想实现一个自动依次显示的两个窗口,而不需要用户与任何窗口进行交互。像这样的:

While True:
    Show Window1    
    wait 2 seconds
    Close Window1
    Show Window2
    wait 2 seconds
    Close Window2

我遇到的问题是主UI线程卡在app.exec_()函数中,所以无法实现开合逻辑。

import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic


class Win1(QMainWindow):
    def __init__(self):
        super(Win1, self).__init__()
        uic.loadUi('win1.ui', self)
        self.show()
        
class Win2(QMainWindow):
    def __init__(self):
        super(Win2, self).__init__()
        uic.loadUi('win2.ui', self)
        self.show()

if __name__ == '__main__':

    app = QApplication(sys.argv)

    while True:
        win = Win1()
        time.sleep(1) 
        win.close()
        
        win = Win2()
        time.sleep(1)
        win.close()
        
        app.exec_() # <--------- Program blocks here

如果有人可以在不阻塞的情况下分享这个工作的最小示例,我将不胜感激。或者请指出应该使用的机制。

【问题讨论】:

将 app.exec_() 移到 While 之外? 【参考方案1】:

如果您打算使用 Qt,那么您应该忘记顺序逻辑,但您必须使用事件来实现逻辑。例如,在您的情况下,您希望每次 T 显示一个窗口并隐藏另一个窗口,以便可以使用 QTimer 和标志来实现:

import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import uic


class Win1(QMainWindow):
    def __init__(self):
        super(Win1, self).__init__()
        uic.loadUi('win1.ui', self)
        self.show()
        

class Win2(QMainWindow):
    def __init__(self):
        super(Win2, self).__init__()
        uic.loadUi('win2.ui', self)
        self.show()


if __name__ == "__main__":

    app = QApplication(sys.argv)

    timer = QTimer()
    timer.setProperty("flag", True)

    win1 = Win1()
    win2 = Win2()

    def on_timeout():
        flag = timer.property("flag")
        if flag:
            win1.show()
            win2.close()
        else:
            win2.show()
            win1.close()
        timer.setProperty("flag", not flag)

    timer.timeout.connect(on_timeout)
    timer.start(1 * 1000)
    on_timeout()

    app.exec_()

您不应该使用 while 循环或 time.sleep,因为它们会阻塞 GUI 所在的事件循环,也就是说:它们会冻结窗口

【讨论】:

嗨 eyllanesc,感谢您的回答。它解决了我发布的当前问题。为此,我想关键是使用 QTimer。感谢您指出了这一点。我想解决的更大问题是创建一个基于状态的 UI,其中基于另一个线程内发生的事件,自动从屏幕上的集合中显示某个屏幕。我想通过这种方法,我可以设置一个小的超时间隔并在计时器内实现状态机,它可以检查程序中的全局变量以确定当前状态。如果有更好的机制来解决这个问题,请发表评论。 @Malik 1) 请阅读 How to Ask 和 How to Answer, 2) 我只解决了 OP 在帖子中显示的问题,仅此而已,所以我不会扩展其他主题,所以如果你有其他问题然后创建另一个帖子。 3) 一般来说(我不知道它是否适用于你的情况)你不应该从另一个线程更新 GUI,而是通过信号通知这些状态,更多信息请阅读***.com/questions/9957195/… @Malik 4)另一方面,有成千上万的帖子(字面意思)关于如何使用 PyQt 中另一个线程的信息更新 GUI,所以我建议您首先调查网站上的其他帖子。 非常感谢。

以上是关于使用 PyQt5,实现两个窗口自动永远循环的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5使用多线程防止卡死

PyQt5 窗口中的多线程

python3+pyQt5+QtDesignner实现窗口化猜数字游戏

PyQt5 窗口在运行几秒钟后自动关闭 - “进程以退出代码 -1073741819 (0xC0000005) 完成”

如何在pyqt5中的两个窗口之间传递参数?

当我在 PyQt5 窗口中嵌入 Matplotlib 图形时,为啥有两个重复的轴标签?