为了账号安全,请及时绑定邮箱和手机立即绑定

PyQt5:同一窗口的多个实例

PyQt5:同一窗口的多个实例

当年话下 2022-08-25 14:06:54
我在使用 pyqt5 时遇到问题。我有这段代码来实例化我的类并打开我的窗口,而无需在 show 方法之后关闭(因为 gc)。def user_crud():  global crud  crud = TCrudUsuario()  crud.show()它工作得很好,但是在TCrudUsuario类上,我有一些按钮连接到带有参数的方法,所以我使用的是lambda(尝试部分,但发生同样的问题),如下所示:self.btnNovo.clicked.connect(lambda: self.manage_user(1))问题是:如果我使用lambda或部分连接到我的方法manage_user(),它允许我打开TCrudUsuario类的多个实例,打开两个或多个窗口。但是,如果我删除连接方法,它只会打开1个窗口。我的目标是只允许一个实例/一个窗口。有谁知道为什么会发生这种情况?可重现代码:from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_test(QtWidgets.QMainWindow):    def __init__(self):        super().__init__()        self.setObjectName("test")        self.resize(380, 250)        self.btntest = QtWidgets.QPushButton(self)        self.btntest.setGeometry(QtCore.QRect(70, 190, 100, 40))        self.btntest.setText('open other window')        self.btntest.clicked.connect(open_otherwindow)class OtherWindow(QtWidgets.QMainWindow):    def __init__(self):        super().__init__()        self.setObjectName("otherwindow")        self.resize(250, 250)        self.button = QtWidgets.QPushButton(self)        self.button.setGeometry(QtCore.QRect(70, 100, 100, 40))        self.button.setText('hello')        self.button.clicked.connect(lambda: self.nothing(1))    def nothing(self, arg):        passdef open_otherwindow():    global w    w = OtherWindow()    w.show()if __name__ == "__main__":    import sys    app = QtWidgets.QApplication(sys.argv)    app.setStyle('Fusion')    test = Ui_test()    test.show()    sys.exit(app.exec_())
查看完整描述

1 回答

?
紫衣仙女

TA贡献1839条经验 获得超15个赞

解释:

要了解问题,必须分析以下 2 个代码及其输出:


示例1


from PyQt5 import QtCore



if __name__ == "__main__":

    app = QtCore.QCoreApplication([])


    o = QtCore.QObject()

    o.destroyed.connect(lambda: print("destroyed o"))


    o = QtCore.QObject()


    def on_timeout():

        print("quit")

        QtCore.QCoreApplication.quit()


    QtCore.QTimer.singleShot(1000, on_timeout)


    app.exec_()

destroyed o

quit

示例 2


from PyQt5 import QtCore



if __name__ == "__main__":

    app = QtCore.QCoreApplication([])


    o = QtCore.QObject()

    o.destroyed.connect(lambda: print("destroyed o"))


    p = o


    o = QtCore.QObject()


    def on_timeout():

        print("quit")

        QtCore.QCoreApplication.quit()


    QtCore.QTimer.singleShot(1000, on_timeout)


    app.exec_()

quit

destroyed o

在第一个示例中,变量“o”被分配了一个QObject,当另一个QObject被分配时,初始QObject被删除,因此在“退出”之前打印“销毁”。


在第二个示例中,它具有差异“p = o”,其中引用QObject,也就是说,在该行中“p”和“o”表示相同的对象,因此通过分配“或”一个新的QObject,初始QObject不会被破坏,并且只有在循环结束时并且GC完成其工作时才被销毁。


这就是在你的情况下以一种微妙的方式发生的事情,“p = o”的逻辑是QObject存储在另一个“地方”,而在你的例子中,“地方”是具有自己作用域的lambda(类似于部分)。具体来说,在您的示例中,创建了一个新窗口,销毁了前一个窗口,从而导致始终显示单个窗口。


溶液:

一种可能的解决方案是防止删除第一个窗口并使用标志创建新窗口:


from PyQt5 import QtCore, QtGui, QtWidgets


flag = False


# ...


def open_otherwindow():

    global w, flag

    if not flag:

        w = OtherWindow()

        w.show()

    flag = True


# ...


查看完整回答
反对 回复 2022-08-25
  • 1 回答
  • 0 关注
  • 206 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信