Python PyQt:单击 X 不会触发 closeEvent

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14834494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:35:43  来源:igfitidea点击:

PyQt: clicking X doesn't trigger closeEvent

pythonpyqtpyqt4

提问by Wookie88

I'm a total newbie in PyQt trying to develop simple application. I have designed simple ui with Qt-designer. I want extra confirmation if the user really want to exit application when clicking X or ,,Exit'' button or choosing Exit from menu.

我是 PyQt 的新手,试图开发简单的应用程序。我用 Qt-designer 设计了简单的 ui。如果用户真的想在单击 X 或 ,,Exit'' 按钮或从菜单中选择退出时退出应用程序,我需要额外的确认。

Here's the code:

这是代码:

import sys
from PyQt4 import QtGui, QtCore, uic

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        self.ui = uic.loadUi('main_window.ui')
        self.ui.show()

        self.ui.btnExit.clicked.connect(self.close)
        self.ui.actionExit.triggered.connect(self.close)

    def closeEvent(self, event):
        print("event")
        reply = QtGui.QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()


def main():
    app = QtGui.QApplication(sys.argv)
    win = MainWindow()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

The problem is that:

问题在于:

  • When I click X on main window the closeEvent function doesn't trigger
  • When I click Exit button or choose ,,Exit'' from menu, the function
    is called, but clicking Yes doesn't close application.
  • 当我在主窗口上单击 X 时,closeEvent 函数不会触发
  • 当我单击退出按钮或从菜单中选择 ,,Exit'' 时,该函数
    被调用,但单击是不会关闭应用程序。

I have found some questions on SO and searched for tutorials, but nothing covered such problem. What am I doing wrong?

我在 SO 上发现了一些问题并搜索了教程,但没有涵盖此类问题。我究竟做错了什么?

采纳答案by Avaris

Note that you're doing:

请注意,您正在执行以下操作:

self.ui = uic.loadUi('main_window.ui')
self.ui.show()

Your actualwindow is an instance attribute (ui) insidewin. Not the winitself. And it doesn't have closeEventimplemented.

您的实际窗口是内部的实例属性 ( ui) 。不是本身。它没有实施。winwincloseEvent

loadUican load the .uifile inside an instance.

loadUi可以.ui在实例中加载文件。

PyQt4.uic.loadUi(uifile[, baseinstance=None[, package='']])

You should use that. With that, your code would be:

你应该用那个。这样,您的代码将是:

import sys
from PyQt4 import QtGui, QtCore, uic

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        uic.loadUi('main_window.ui', self)

        self.btnExit.clicked.connect(self.close)
        self.actionExit.triggered.connect(self.close)

    def closeEvent(self, event):
        print("event")
        reply = QtGui.QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()


def main():
    app = QtGui.QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

Note: I'm not a fan of showing the window in __init__. Explicit is better. So, I moved that to main. Feel free to modify it.

注意:我不喜欢show__init__. 明确的更好。所以,我把它移到了main. 随意修改它。

回答by LtWorf

From the designer you can connect events to the main window, and add new slots to it in the designer, then just implement the methods in python and the event->slot connection will be done automatically.

从设计器中,您可以将事件连接到主窗口,并在设计器中为其添加新槽,然后只需在 python 中实现方法,事件->槽连接将自动完成。

回答by Anggun Pribadi

it works for me, just adding this line

它对我有用,只需添加这一行

self.ui.closeEvent = self.closeEvent

so your code would be:

所以你的代码是:

import sys
from PyQt4 import QtGui, QtCore, uic

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        self.ui = uic.loadUi('main_window.ui')
        self.ui.closeEvent = self.closeEvent
        self.ui.show()

        self.ui.btnExit.clicked.connect(self.close)
        self.ui.actionExit.triggered.connect(self.close)

    def closeEvent(self, event):
        print("event")
        reply = QtGui.QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()


def main():
    app = QtGui.QApplication(sys.argv)
    win = MainWindow()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

回答by Natesh bhat

Another simple solution for this is using the app.aboutToQuit.connect(self.close_event)to run the code in the closeEventfunction whenever the user clicks the close button.

另一个简单的解决方案是在用户单击关闭按钮时使用app.aboutToQuit.connect(self.close_event)运行closeEvent函数中的代码。

Sample code here

示例代码在这里

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

#--------------------------------------------------------------------------------

        app.aboutToQuit.connect(self.closeEvent) #this line is what ur looking for !!!!!!

#--------------------------------------------------------------------------------

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle('Demo')

    #{______________________________________

    def closeEvent(self):
        #Your code here
        print('User has pressed the close button')
        import sys
        sys.exit(0)

    #}______________________________________


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)