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

yak*_*ang 6 c++ user-interface qt qt5

我有两个类AB,这里是一个片段中B.h:

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

并在B.cpp:

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

所以,我应该怎么做,如果我想打电话do_something()的时候uiA关闭(按Alt-F4,例如)?似乎在signal-slot这里不适用的方式.
非常感谢 !

hyd*_*yde 6

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

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

使用Qt信号删除QObject

如果你可以设置Qt::WA_DeleteOnClose属性A,然后简单的方法就是让B::doSomething()(注意常见的Qt方法命名约定)插槽和连接destroyed信号一个实例了这一点.

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();
}
Run Code Online (Sandbox Code Playgroud)

当然,即使您delete a;明确地使用,也不会自动使用该属性.

注:在这种情况下,当对象可能会被删除时,你应该使用QPointera指针,以避免意外引用一个悬摆指针.

使用Qt事件过滤器

如果您不希望A实例在关闭时被删除(如果再次需要则重新创建),那么另一种方法是在A实例上安装事件过滤器,并检测closeEvent.这有一个潜在的问题,即窗口小部件可以拒绝关闭事件,并且在任何情况下doSomething都会在关闭之前调用.如果这是一个问题,可以通过使用QMetaObject::invokeMethod静态方法来延迟doSomething(在事务结束后,它必须是插槽或可调用的方法!)调用才能解决,并且程序返回到事件循环.然后doSomething检查是否a真的隐藏了.而不是QEvent::Close,检测QEvent::Hide可能也很好.

要实现这一点,请覆盖B中的虚拟eventFilter方法,如下所示:

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);
}
Run Code Online (Sandbox Code Playgroud)

然后A使用installEventFilter开始侦听实例的事件,例如:

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