在QT中,如何在收到孩子生成的信号后从父母中删除子窗口小部件?

时间:2018-04-29 04:05:00

标签: c++ qt qt5 qt-signals

在QT中,如何在收到孩子产生的信号后从父母中移除子窗口小部件?

我正在使用QT 5.7并编写一个带有2个widget,view1和view2的简单程序。 view1中有一个名为“btn_1”的按钮,view2中有一个名为“btn_leave”的按钮。

当您单击“btn_1”时,它将生成一个view2对象并将其添加到view1的布局中。我希望在单击“btn_leave”时删除view2。

这是我的想法。在view2中单击leave_btn时,它会发出一个名为“leave”的信号。我将此信号连接到lambda函数以删除view2。

void VIEW1::on_btn_1_clicked() {
    VIEW2 *view2 = new VIEW2();
    layout->addWidget(view2);

    connect(view2, &VIEW2::leave, this, [&view2]() {
        delete view2;
    });
}

程序崩溃并不奇怪,因为我在从view2发出信号时删除了view2。发出请假信号后,view2可以访问其成员。

所以我用deleteLater重写它。根据QT文档,当控制返回到事件循环时,该对象将被删除。

void VIEW1::on_btn_1_clicked() {
    VIEW2 *view2 = new VIEW2();
    layout->addWidget(view2);

    connect(view2, &VIEW2::leave, this, [&view2]() {
        view2.deleteLater();
    });
}

但令人惊讶的是,该计划再次遭遇崩溃。有没有什么我误解了deleteLater的用法,或者在调用deletelater()之后在事件队列访问view2中还有一些事件?

如果有帮助,我已将我的整个程序(使用QT创建者创建)上传到github

1 个答案:

答案 0 :(得分:4)

你必须传递view2的指针,而不是指针的指针,除了this之外没有必要。

void VIEW1::on_btn_1_clicked() {
    VIEW2 *view2 = new VIEW2();
    layout->addWidget(view2);

    connect(view2, &VIEW2::leave, [view2]() {
        view2->deleteLater();
    });
}

或者只是不使用lambda函数,而是使用new connection style

void VIEW1::on_btn_1_clicked() {
    VIEW2 *view2 = new VIEW2();
    layout->addWidget(view2);
    connect(view2, &VIEW2::leave, view2, &VIEW2::deleteLater);
}

另一个选择是不创建leave信号,并连接点击信号

VIEW2::VIEW2(QWidget *parent) :
    QWidget(parent)
{
    label = new QLabel(this);
    label->setText("view2");
    btn_leave = new QPushButton(this);
    btn_leave->setText("leave");

    layout = new QHBoxLayout;
    layout->addWidget(label);
    layout->addWidget(btn_leave);
    setLayout(layout);

    connect(btn_leave, &QAbstractButton::clicked, this, &VIEW2::deleteLater);
}