PyQt5:同一窗口的多个实例 [英] PyQt5: multiple instances of same window

查看:1600
本文介绍了PyQt5:同一窗口的多个实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对pyqt5有问题.我有这段代码可以实例化我的类,并在show方法之后关闭窗口,而无需关闭(因为gc).

I'm having a problem with pyqt5. I have this piece of code to instantiate my class and open my window without closing after the show method (because gc).

def user_crud():
  global crud
  crud = TCrudUsuario()
  crud.show()

它运作良好,但是在TCrudUsuario类上,我有一些按钮连接到带有参数的方法,因此我使用的是lambda(尝试使用部分参数,但同样会发生问题),如下所示:

it works well, but on the TCrudUsuario class, I have some buttons that connects to a method with arguments, so I'm using a lambda (tried with partial, but the same problem happens), something like this:

self.btnNovo.clicked.connect(lambda: self.manage_user(1))

问题是:如果我使用lambda或Partial连接到我的方法 manage_user(),它将允许我打开TCrudUsuario类的多个实例,并打开两个或更多窗口.但是,如果我删除connect方法,它将仅打开1个窗口.我的目标是只允许一个实例/一个窗口.有谁知道为什么会这样?

the problem is: if I use a lambda or partial to connect to my method manage_user(), it allows me to open multiple instances of TCrudUsuario class, opening two or more windows. but, if I remove the connect method, it only opens 1 window. My goal is to allow only one instance/one window. does anyone know why this happens?

可复制的代码:

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个代码及其输出:

Explanation:

To understand the problem, the following 2 codes and their outputs must be analyzed:

示例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

Example2

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"之前.

In the first example, the variable "o" is assigned a QObject and when another QObject is assigned, the initial QObject is deleted, so "destroyed" is printed before "quit".

在第二个示例中,当引用QObject时,其差异为"p = o",也就是说,在该行中,"p"和"o"代表相同的对象,因此可以通过分配或" a新的QObject最初的QObject不会被销毁,只有在循环结束且GC完成其工作时才会销毁.

In the second example, it has the difference "p = o" where reference is made to the QObject, that is, in that line "p" and "o" represent the same object, so by assigning "or" a new QObject the initial QObject is not it destroys, and it is only destroyed when the loop ends and the GC does its job.

这就是您的情况以一种微妙的方式发生的情况,"p = o"的逻辑是QObject存储在另一个位置"中,而在您的示例中,位置"是具有自己的lambda范围(类似局部).具体来说,在您的示例中,创建了一个新窗口来销毁前一个窗口,从而始终显示一个窗口.

That is what happens in your case in a subtle way, the logic of "p = o" is that the QObject is stored in another "place", and in your example that "place" is the lambda that has its own scope ( similarly with partial). Specifically, in your example, a new window was created destroying the previous one, causing a single window to be displayed at all times.

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

One possible solution is to prevent the first window from being removed and a new window created using a flag:

from PyQt5 import QtCore, QtGui, QtWidgets

flag = False

# ...

def open_otherwindow():
    global w, flag
    if not flag:
        w = OtherWindow()
        w.show()
    flag = True

# ...

这篇关于PyQt5:同一窗口的多个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆