在QT关闭窗口之前获取应用程序退出信号

时间:2017-12-11 20:52:38

标签: qt pyqt pyqt5

我有一个带有多个主窗口的Qt应用程序,并希望在应用程序即将退出时获取信号,而所有窗口仍在运行。

QApplication.aboutToQuit信号对我不起作用,因为它仅在所有窗口关闭后触发。

我见过的所有其他答案建议实现主窗口的closeEvent()函数,但我有多个主窗口,我找不到任何方法来区分CloseEvent在正常closeEvent之间只有一个窗口被关闭,一个关闭事件发生在整个应用程序在QMD+Q之后关闭或者在任务栏中使用单击退出时,或者出于任何原因退出。

只有当整个应用程序即将退出但在关闭任何窗口之前,我该如何获得信号?

当我按下Cmd + Q或右键单击退出任务栏图标时会发生什么:

  1. (此时我想要一个信号)< -
  2. 所有窗口都有一个closeEvent()
  3. aboutToQuit()触发
  4. app退出
  5. 我想要的是在任何一个发生之前得到一个信号并且所有的窗户仍然打开。

    编辑:最小例子

    from PyQt5.QtGui import QCloseEvent
    from PyQt5.QtWidgets import QApplication, QWidget
    
    class Win(QWidget):
        def closeEvent(self, event: QCloseEvent):
            # implementing a custom closeEvent doesn't help me
            # this is called for every normal manual window close and when the application quits
            # I only want to run something when the full application gets shut down, not just this window
            # can't see any way to differentiate between the two
            print("closeEvent", event.type(), event)
            return super().closeEvent(event)
    
    
    if __name__ == '__main__':
        app = QApplication([])
        app.aboutToQuit.connect(lambda :print("about to quit, this is too late, by now all windows are closed"))
    
        #What I need
        # app.beforeQuitSignal.connect(lambda :print("signal that it's gonna quit, before any of the windows are closed"))
    
        #stuff I've tried that didn't work either
        app.quit = lambda *args:print("quit, doesnt get called")
        app.exit = lambda *args:print("exit, doesnt get called")
        app.closeAllWindows = lambda *args:print("closeAllWindows, doesnt get called")
    
        mainwins = []
        for i in range(5):
            win = Win()
            win.setGeometry(100*i,100*i, 400,400), win.show(), win.raise_()
            mainwins.append(win)
    
        app.exec_()
    

3 个答案:

答案 0 :(得分:0)

如果是CloseEvent,您可以对spontaneous进行过滤:

from PyQt5.QtCore import pyqtSignal, QEvent
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import QApplication, QWidget


class Win(QWidget):
    closing = pyqtSignal()
    def closeEvent(self, event: QCloseEvent):
        self.closing.emit()
        if event.type() == QEvent.Close and event.spontaneous():
            event.ignore()
        else:
            return super().closeEvent(event)


class MyApp(QApplication):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

        self.mainwins = []
        for i in range(5):
            win = Win()
            win.closing.connect(self.beforeQuit)
            win.setGeometry(100 * i, 100 * i, 400, 400), win.show(), win.raise_()
            self.mainwins.append(win)

    def beforeQuit(self):
        print("Exiting")
        # Do what you want here ...
        self.exit()  # Terminate the QApplication

if __name__ == '__main__':
    app = MyApp([])
    app.exec_()

答案 1 :(得分:0)

如果您想在用户关闭窗口时触发信号但在最后一个窗口关闭后不立即退出QApplication,则可以使用QApplication.setQuitOnLastWindowClosed()

from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import QApplication, QWidget


class Win(QWidget):
    closing = pyqtSignal()

    def closeEvent(self, event: QCloseEvent):
        print("Window {} closed".format(self))
        self.closing.emit()
        return super().closeEvent(event)


class MyApp(QApplication):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

        self.setQuitOnLastWindowClosed(False)
        self.lastWindowClosed.connect(self.onLastClosed)

        self.mainwins = []
        for i in range(5):
            win = Win()
            win.setGeometry(100 * i, 100 * i, 400, 400), win.show(), win.raise_()
            self.mainwins.append(win)

    def onLastClosed(self):
        print("Last windows closed, exiting ...")
        self.exit()


if __name__ == '__main__':
    app = MyApp([])
    app.exec_()

这样,当窗口关闭时,会发出closing()信号

答案 2 :(得分:0)

使用 installEventFilter 在任何窗口关闭之前拦截应用程序的退出事件:

class AppManager(QObject):
    def __init__(self):
        super().__init__()
        qApp.installEventFilter(self)

    def eventFilter(self, obj, event):
        if event.type() == QEvent.Quit:
            self.saveWindowStates()
        return False

    def saveWindowStates(self):
        # code to save the application's state
相关问题