pyside2 通过 Window "X" 关闭连接到自定义退出方法

pyside2 connect close by Window "X" to custom exit method

我正在为 GUI 布局使用 Qt Designer,并在 QUILoader 的帮助下将 .ui 文件加载到 python。

我设法将 'Quit' 按钮连接到我的 'quit_app' 方法。

我的问题是如果用户试图用 'X' 关闭 Window。

时如何连接此方法

提前致谢!

---> PYTHON 代码 <---

import sys
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QFile

class main_w(object):
    def __init__(self):
        # load ui; create w
        self.file = QFile("simple_quit.ui")
        self.file.open(QFile.ReadOnly)
        self.loader = QUiLoader()
        self.w = self.loader.load(self.file)

        # connections

        # Quit Button
        self.w.QUITButton.clicked.connect(self.quit_app)

        # ??? Window's X Button ???
        # THROWS ERROR:
        self.w.closeEvent.connect(self.quit_app)

    def quit_app(self):
        # some actions to perform before actually quitting:
        print('CLEAN EXIT')
        app.exit()

    def show(self):
        self.w.show()

app = QApplication(sys.argv)
w = main_w()
w.show()
sys.exit(app.exec_())

---> UI XML <---

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="QUITButton">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>100</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>quit</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

在 Qt 中有两个概念:信号和事件,信号连接到一个插槽,但在事件的情况下你不能,然后你有后者。对于signal,因为在connection中声明了就知道谁是receiver,但是events不是,这个是通过QObjects的父子关系树发送的,可以接受或视情况忽略。

这就是你遇到这个问题的原因。


一般的解决方案是覆盖 closeEvent 方法:

C++ 版本:

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (maybeSave()) {
        writeSettings();
        event->accept();
    } else {
        event->ignore();
    }
}

Python版本:

def closeEvent(self, event):
    if maybeSave():
        writeSettings()
        event.accept()
    else:
        event.ignore()

但是为此有必要从class继承,但在你的情况下这是不可能的所以还有另一种解决方案,安装一个事件过滤器:

import sys
from PySide2 import QtCore, QtWidgets, QtUiTools


class Manager(QtCore.QObject):
    def __init__(self):
        super(Manager, self).__init__()
        # load ui; create w
        file = QtCore.QFile("simple_quit.ui")
        file.open(QtCore.QFile.ReadOnly)
        loader = QtUiTools.QUiLoader()
        self.w = loader.load(file)

        # connections
        # Quit Button
        self.w.QUITButton.clicked.connect(self.quit_app)

        self.w.installEventFilter(self)

    def eventFilter(self, obj, event):
        if obj is self.w and event.type() == QtCore.QEvent.Close:
            self.quit_app()
            event.ignore()
            return True
        return super(Manager, self).eventFilter(obj, event)

    @QtCore.Slot()
    def quit_app(self):
        # some actions to perform before actually quitting:
        print('CLEAN EXIT')
        self.w.removeEventFilter(self)
        app.quit()

    def show(self):
        self.w.show()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Manager()
    w.show()
    sys.exit(app.exec_())
def closeEvent(self, event):
    if pendingChanges == True: #write your required condition/check 
        self.save()            #include required your functionality(eg. self.save())         
        event.accept()
    else:
        event.ignore()