退出应用程序时获取closeEvent



我正在尝试制作一个能够拥有多个窗口的小型python程序。问题是当我试图实现一个菜单项来退出程序,同时关闭所有窗口时。我曾尝试使用qApp.close()qApp.exit(),但如果它们允许有效地退出程序,则不会为仍打开的窗口生成关闭事件,这会阻止我保存修改后的数据或阻止我离开应用程序。最好的做法是什么?我可以理解不能取消退出过程,但能够提议保存修改后的数据是我真正想要的。

import sys
from PyQt5.QtWidgets import *
opened_windows = set()

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.create_actions()
opened_windows.add(self)
def closeEvent(self, ev):
if QMessageBox.question(self, 'Closing', 'Really close?') == QMessageBox.Yes:
ev.accept()
opened_windows.remove(self)
else:
ev.ignore()
def create_action(self, action_callback, menu, action_name):
action = QAction(action_name, self)
action.triggered.connect(action_callback)
menu.addAction(action)
def create_actions(self):
_file_menu = self.menuBar().addMenu('&File')
self.create_action(self.on_new, _file_menu, '&New')
_file_menu.addSeparator()
self.create_action(self.on_close, _file_menu, '&Close')
self.create_action(self.on_quit, _file_menu, '&Quit')
self.create_action(self.on_exit, _file_menu, '&Exit')
def on_new(self):
win = MainWindow()
win.show()
def on_close(self):
self.close()
def on_quit(self):
qApp.quit()
def on_exit(self):
qApp.exit(1)

if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
status = app.exec()
print(len(opened_windows), ' window(s) opened')
print('status = ', status)
sys.exit(status)

目前我正在修改on_closeon_exit,如下所示:

def on_exit(self):
for w in opened_windows.copy():
w.on_close()
if len(opened_windows) == 0:
qApp.exit(1)

但我想知道我是否错过了一个更好的方法,它不会强迫我维护一组打开的窗户。

原因

重要的是要理解,应用程序和主窗口是相关的,但不是同一回事。所以,当你想关闭程序时,不要麻烦关闭应用程序。请关闭主窗口。来自QCloseEvent的文档:

关闭事件发送到用户想要关闭的窗口小部件,通常通过从窗口菜单中选择"关闭"或单击X标题栏按钮。当您调用QWidget::close((以编程方式关闭小部件时,也会发送它们。

解决方案

  1. 将退出操作的triggered信号连接到MainWindowclose插槽。在您的情况下,而不是:

    self.create_action(self.on_exit, _file_menu, '&Exit')
    

    写入:

    self.create_action(self.close, _file_menu, '&Exit').
    
  2. MainWindow中定义信号closed,并从closedEvent的实现中发射,例如在opened_windows.remove(self)的位置

  3. on_new中,将win.closed连接到self.close

示例

以下是我建议您如何更改代码以实现所提出的解决方案:

import sys
from PyQt5.QtWidgets import * 
class MainWindow(QMainWindow):
closed = pyqtSignal()
def __init__(self):
super().__init__()
self.create_actions()
def closeEvent(self, ev):
if QMessageBox.question(self, 'Closing', 'Really close?') == QMessageBox.Yes:
ev.accept()
self.closed.emit()
else:
ev.ignore()
def create_action(self, action_callback, menu, action_name):
action = QAction(action_name, self)
action.triggered.connect(action_callback)
menu.addAction(action)
def create_actions(self):
_file_menu = self.menuBar().addMenu('&File')
self.create_action(self.on_new, _file_menu, '&New')
_file_menu.addSeparator()
self.create_action(self.close, _file_menu, '&Exit')
def on_new(self):
win = MainWindow()
win.show()
win.closed.connect(self.close)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
status = app.exec()
print('status = ', status)
sys.exit(status)

编辑:我想知道我以前是怎么错过的。有一个QApplication::closeAllWindows插槽,它正是我想要的,其示例是绑定退出。


有一种方法可以建议保存quitexit上的修改数据,即信号QCoreApplication::aboutToQuit

注意,尽管Qt文档说用户交互是不可能的,但至少在PyQt5中,我可以在没有明显问题的情况下使用QMessageBox。

相关内容

  • 没有找到相关文章

最新更新