Qt QMainWindow关闭事件

13

这个问题看起来非常简单,但是我想在 QMainWindow 关闭时转储一些数据,因此我使用了以下代码:

QObject::connect(MainWindow.centralwidget, SIGNAL(destroyed()), this, SLOT(close()));

但是这似乎并没有使它调用close()。我做错了吗?
centralwidget难道不应该被销毁吗?

或者说应用程序在close()被调用之前就关闭了?

还有其他的方法吗?


this 在你的 QObject 层次结构中的位置是什么?可能会在信号发送之前被删除。当然,我不会太担心它,因为到目前为止给出的答案中有更好的替代方案。 - Troubadour
你不能使用你展示的代码转储数据... 另外,你的问题是如何在QMainWindow关闭之前转储数据?还是为什么QMainWindow没有关闭?请明确表述。 - liaK
1
我想在单击“x”关闭主窗口后编写XML文件。似乎无法使用上面的代码或QApplication :: lastWindowClosed()(或QApplication :: aboutToQuit())来实现此目的...尚未尝试QCloseEvent,但为了保持MVC结构,我宁愿不这样做。我正在使用的类不是QMainWindow,而是使用在设计师中制作的ui文件编译得到的文件。 - Cenoc
您可以通过重写closeEvent来发射信号来保持MVC。 - Adam W
7个回答

31

您最好在主MainWindow类中重新实现一个虚函数,如下所示:

class MainWindow : public QMainWindow {

    Q_OBJECT;

public:
    MainWindow();

protected:
     void closeEvent(QCloseEvent *event);
}

然后在源文件中声明:

void MainWindow::closeEvent(QCloseEvent *event) {
     // do some data saves or something else
}

祝您好运。


2
完善覆盖是个好主意。例如在closeEvent()函数的末尾调用QMainWindow::closeEvent(event)。在这里查看saveState()函数文档中的示例:http://doc.qt.io/qt-4.8/qmainwindow.html - Ph0t0n
1
尽管 Ph0t0n 可能没有错,但实际的 closeEvent() 实现通常会根据是否存在未保存的更改而调用 event.accept()event.ignore()。通常不会调用 QMainWindow::closeEvent(event)。参见 closeEvent() 文档 获取另一个有用的示例。 - Cecil Curry

10

没起作用,这一定意味着在信号被接受之前它就被销毁了?但是这很奇怪,因为该类的析构函数似乎没有输出任何东西(通过 std::cerr)。 - Cenoc
确保带插槽的对象不是QMainWindow的子级。当QWidgets关闭时,它们会销毁它们的所有子级。 - György Andrasek
@Cenoc:请发布你的“main”函数,这可以帮助澄清情况。 - Adam W
哇,好的发现,它起作用了!非常感谢!肯定不会在QApplication中寻找这个。 - Cenoc

4

你能在你的QMainWindow中实现closeEvent函数并将代码放在那里吗?


3

enter image description here 在Python中(使用pyqt4或pyqt5),您需要执行以下操作:

class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        #
        # My initializations...
        #

    ''''''

    def closeEvent(self, *args, **kwargs):
        #
        # Stuff I want to do when this
        # just before (!) this window gets closed...
        #

    ''''''

有趣的是,closeEvent(..) 函数中的内容会在窗口关闭之前执行。您可以使用以下测试进行验证:

    # Test if the closeEvent(..) function
    # executes just before or just after the window closes.
    def closeEvent(self, *args, **kwargs):
        # 'self' is the QMainWindow-object.
        print(self)
        print(self.isVisible())

        # Print out the same stuff 2 seconds from now.
        QTimer.singleShot(2000, lambda: print(self))
        QTimer.singleShot(2100, lambda: print(self.isVisible()))

    ''''''

这是您终端的输出结果:
<myProj.MyWindow object at 0x000001D3C3B3AAF8>
True

<myProj.MyWindow object at 0x000001D3C3B3AAF8>
False

这证明在进入closeEvent(..)函数时,窗口仍然可见,但在退出该函数后不可见。

1
在你的类中实现 QMainWindow::closeEvent(QCloseEvent *)。然后实现一个名为 closing() 的新信号,并从 QMainWindow::closeEvent() 的实现中发射它。然后,您可以连接到该信号以在窗口关闭之前执行某些操作。您还可以直接使用 closeEvent 来做您需要做的事情,比如保存状态、同步数据或其他。

1

你的初始问题和代码不匹配。如果你想在 QMainWindow 上做一些事情,可以创建一个子类并重新实现 closeEvent 或连接到 MainWindow::destroyed()。但是请注意第三段的说明。

但是你的代码显示了一个似乎是第三个类的东西,它将 MainWindow 的子项连接到某个名为 close() 的插槽上。 centralwidget 将在 MainWindow 被销毁后被销毁,所以这很可能对你没有帮助。

此外,这取决于你如何创建 MainWindow(堆栈或堆)以及是否正确地销毁它。理想情况下,你应该创建一个 QMainWindow 的子类(如果你使用了设计器,你可能已经有了)。


-2

在你的主窗口析构函数中加入dump代码怎么样?


你不能在MainWindow的销毁器中或销毁之后访问I/O,因为此时你已经进入应用程序的销毁器并且所有内容都已经被销毁。请使用closeEvent()代替。 - Jens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接