Qt - 当另一个对话框关闭时,如何做我想要的?

时间:2013-12-03 13:57:20

标签: c++ qt user-interface qt5

我有两个课程AB,这是B.h中的一个片段:

#include "A.h"
class B : public QDialog
{
    Q_OBJECT
public:
    void do_something();
private:
    A *a;
}

B.cpp

B::B(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::B)
{
    a = new A();
    a.show();
}

那么如果我想在do_something() ui被关闭时(例如按A),我应该怎么做?似乎Alt-F4的方式在这里不适用。
非常感谢!

2 个答案:

答案 0 :(得分:6)

修改A类以在关闭时发出信号

如果修改A小部件是选项,请向其添加信号并覆盖closeEventhideEvent并在那里发出新信号。这很强大,您可以完全控制发生的事情。然而,答案的其余部分是出于这样的情况,无论如何,您无法或不愿意混淆A并希望在B类中找到解决方案。

使用Qt信号进行QObject删除

如果您可以在A上设置Qt::WA_DeleteOnClose attribute,那么简单的方法就是使B::doSomething()(注意常见的Qt方法命名约定)成为一个插槽并连接destroyed signal的A实例。

B::B(QWidget *parent) : QDialog(parent), ui(new Ui::B)
{
    a = new A();
    a->setAttribute(Qt::WA_DeleteOnClose);
    connect(a, SIGNAL(destroyed(QObject*)), SLOT(doSomething()));
    a.show();
}

当然,即使您delete a;明确地使用,也不会自动使用该属性,这种情况也会有效。

注意:在这种情况下,当对象可能随时被删除时,您应该使用QPointer作为a指针,以避免意外引用悬空指针。

使用Qt事件过滤器

如果您不希望A实例在关闭时被删除(如果再次需要则重新创建),那么另一种方法是在A实例上安装事件过滤器,并检测{{3 }}。这有一个潜在的问题,即窗口小部件可以拒绝close事件,并且在关闭之前调用doSomething。如果这是一个问题,可以通过使用closeEvent来延迟doSomething(它必须是插槽或可调用的方法!)调用在close事件结束并且程序返回事件后发生环。然后在doSomething中检查a是否真的被隐藏了。检测QEvent::Close可能效果不错,而不是QEvent::Hide

要实现此功能,请覆盖B中的虚拟QMetaObject::invokeMethod static method,如下所示:

bool B::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::Close) { //or QEvent::Hide maybe
        qDebug("QCloseEvent!");

        // check that object is indeed this->a before calling this->doSomething()
        if (qobject_cast<QObject *>(a) == obj) {
            doSomething();
            //alternative, make doSomething to be called later from event loop:
            //QMetaObject::invokeMethod(this, "doSomething", Qt::QueuedConnection);
        } else {
            qDebug("...but the object is not what is expected, a bug?");
        }
        // do not block the event, just detect it
    }

    // proceed with standard event processing
    return QObject::eventFilter(obj, event);
}

然后开始使用eventFilter method监听A个实例的事件,例如:

B::B(QWidget *parent) : QDialog(parent), ui(new Ui::B)
{
    a = new A();
    installEventFilter(a);
    a.show();
}

答案 1 :(得分:3)

如果你不能使用模态窗口(或对话框),那么你需要继承QWidget(或QDialog或其他QWidget派生类,无论你需要什么)并覆盖{{3} }(对于类 A )并从此处调用父项的方法(我假设 a 将是代码中 this 的子项: a = new A(this); )或编码您自己的信号/插槽。

如果您决定使用模态对话框,代码会变得更简单,请参阅QDialog的QWidget::closeEvent中的示例代码。