繁体   English   中英

PyQt5:同一窗口的多个实例

[英]PyQt5: multiple instances of same window

我在使用 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, QtWidgets


class 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):
        pass

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

解释:

要理解问题,必须分析以下 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 被删除,所以 "destroyed" 在 "quit" 之前打印。

在第二个例子中,它有区别“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

# ...

暂无
暂无

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

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