在 QtWidgets 的 PyQt5 中按下角落的红色 x 按钮时如何处理/覆盖?

Posted

技术标签:

【中文标题】在 QtWidgets 的 PyQt5 中按下角落的红色 x 按钮时如何处理/覆盖?【英文标题】:How to handle/override when the red x button in the corner is pressed in PyQt5 for QtWidget? 【发布时间】:2019-08-09 11:41:16 【问题描述】:

我在 PyQt5 中创建了一个 gui,并且有几个窗口类由一个名为 Controller 的类控制。

背景: 在其中一个窗口(A)中,您可以按下按钮,然后会弹出一个新窗口(B),并且 A 被禁用。然后,当从窗口 B 按下退出按钮时,它会返回到窗口 A,而不在窗口 B 中保存编辑并启用窗口 A,如果在 B 中按下继续按钮,则重新打开窗口 A 并启用它。

问题: 但是,当按下窗口 B 角落的 x 按钮时,窗口关闭,窗口 A 被禁用。因此,我的问题是:当 B 关闭时,如何使窗口 A 再次启用? 我可以覆盖红角 x 事件,以便能够再次启用窗口 A 吗?

PS!我试图使代码最小化和可重复,如果有什么我应该修复的,请告诉我:)

import sys
from PyQt5 import QtCore, QtWidgets

class WindowTwo(QtWidgets.QWidget):
    switch_window = QtCore.pyqtSignal()
    def __init__(self, M, S):
        QtWidgets.QWidget.__init__(self)
        self.S              = S
        self.M              = M
        self.setupUi                         (   self )
        self.setWindowTitle                  (  'M'   )
    def setupUi(self, CM):
        CM.setEnabled             (   True    )
        CM.setFocusPolicy         (   QtCore.Qt.TabFocus   )
        layout = QtWidgets.QGridLayout()
        layout.addWidget(QtWidgets.QLabel("M: " ),0,0)
        layout.addWidget(QtWidgets.QLabel("S: " ),0,1)
        self.QuitButton      = QtWidgets.QPushButton ( "Quit"     )
        self.QContinueButton = QtWidgets.QPushButton ( "Continue"      )
        self.QuitButton.clicked.connect  ( CM.close        )
        self.QContinueButton.clicked.connect( lambda: self.windowtwo(self.M))
        layout.addWidget( self.QuitButton, 10, 1    )
        layout.addWidget ( self.QContinueButton, 10, 2         )

        self.setLayout   ( layout )
    def windowtwo( self, M):
        self.M = M
        self.switch_window.emit()

class MS(QtWidgets.QWidget):
    switch_window = QtCore.pyqtSignal(int)
    def __init__(self, M, S):
        QtWidgets.QWidget.__init__(self)
        self.S              = S
        self.M              = M
        self.setupUi                         (   self )
        self.setWindowTitle                  (  'M'   )
    def setupUi(self, CM):
        CM.setEnabled             (   True    )
        CM.setFocusPolicy         (   QtCore.Qt.TabFocus   )
        layout = QtWidgets.QGridLayout()
        layout.addWidget(QtWidgets.QLabel("M: " ),0,0)
        layout.addWidget(QtWidgets.QLabel("S: " ),0,1)
        self.QWindowTwoButton = QtWidgets.QPushButton ( ' Go to other window')
        self.QuitButton      = QtWidgets.QPushButton ( "Quit"     )
        self.QContinueButton = QtWidgets.QPushButton ( "Continue"      )
        self.QuitButton.clicked.connect  ( CM.close        )
        self.QWindowTwoButton.clicked.connect( lambda b=0, a= 400 : self.windowms(a))
        layout.addWidget( self.QuitButton, 10, 1    )
        layout.addWidget ( self.QContinueButton, 10, 2         )
        layout.addWidget ( self.QWindowTwoButton, 10, 3         )

        self.setLayout   ( layout )
    def windowms( self, a):
        a = 100
        self.switch_window.emit(a)


class Controller:

    def __init__(self):
            self.M                    = 5
            self.S                    = 7
            self.A                    = 8
            # pass


    def show_window_two(self):
        self.window_two = WindowTwo(self.M, self.S)
        self.window_two.switch_window.connect(self.show_window_three)
        self.window_two.show()


    def show_window_three(self):
        try:
            self.A = self.window_four.A
        except:
            pass
        self.window_three = MS(self.M, self.S)
        self.mscrollArea = QtWidgets.QScrollArea()
        self.mscrollArea.setWidget(self.window_three)
        self.mscrollArea.setDisabled(0)
        self.window_three.switch_window.connect(self.show_window_four)
        self.window_three.QuitButton.clicked.connect(self.mscrollArea.close)

        self.mscrollArea.show()
        self.mscrollArea.resize(700, 500)
        self.mscrollArea.setWindowTitle("MS")

        self.window_two.close()
        try: 
            self.window_four.close()
        except:
            pass

    def show_window_four(self, a):
        if (a == 100):
            self.window_four = WindowTwo(self.M, self.S)
            self.window_four.switch_window.connect(self.show_window_three)
            self.mscrollArea.setDisabled(1)
            self.window_four.QuitButton.clicked.connect(lambda: self.window_four.close)
            self.window_four.QuitButton.clicked.connect(lambda: self.mscrollArea.setDisabled(0))
            self.window_four.show()
       #Here is an else if a is other values to open other windows

def main():
    app = QtWidgets.QApplication(sys.argv)
    controller = Controller()
    controller.show_window_two()
    sys.exit(app.exec_())



if __name__ == '__main__':
    main()

【问题讨论】:

什么是show_first?提供minimal reproducible example 谢谢,现在编辑,我的意思是 show_window_two() M 中的self.QContinueButton.clicked.connect( lambda: self.windowms(M)) 是什么,错误:Traceback (most recent call last): File "main.py", line 21, in <lambda> self.QContinueButton.clicked.connect( lambda: self.windowtwo(M)) NameError: name 'M' is not defined 请花时间确保您提供了一个可行的代码。 现在可以重现了!谢谢 【参考方案1】:

closeEvent 会在小部件关闭时触发,例如通过单击角落中的“X”。只需用您自己的代码覆盖它以再次显示主窗口,或发出信号通知您的控制器。

from PyQt5 import QtWidgets
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([])

class W1(QtWidgets.QWidget):    
    def closeEvent(self, event):
        print("closing w1")

class W2(QtWidgets.QWidget):    
    def __init__(self, w1):
        super().__init__()
        self.w1 = w1        

    def closeEvent(self, event):
        print("closing w2")
        self.w1.show()

w1 = W1()
w2 = W2(w1)

w2.show()
app.exec_()

【讨论】:

以上是关于在 QtWidgets 的 PyQt5 中按下角落的红色 x 按钮时如何处理/覆盖?的主要内容,如果未能解决你的问题,请参考以下文章

在 PyQt5 中按下时如何切换按钮文本

如何检测在 PyQt5 中按下了动态添加的按钮之一? [复制]

Pylint 中的模块“PyQt5.QtWidgets”错误中没有名称“QApplication”

Pylint 中的模块“PyQt5.QtWidgets”错误中没有名称“QApplication”

Pylint 中的模块“PyQt5.QtWidgets”错误中没有名称“QApplication”

我对 PyQt5.QtWidgets 有疑问