В QT, как удалить дочерний виджет из родительского после получения сигнала, генерируемого дочерним? - PullRequest
0 голосов
/ 29 апреля 2018

Как в QT удалить дочерний виджет из родительского после получения сигнала, генерируемого дочерним?

Я использую QT 5.7 и пишу простую программу с 2 виджетами, view1 и view2. Внутри view1 есть кнопка с именем «btn_1», а внутри view2 - кнопка с именем «btn_leave».

Когда вы нажимаете «btn_1», он генерирует объект view2 и добавляет его в макет view1. Я хочу, чтобы view2 был удален при нажатии "btn_leave".

Вот моя мысль. При щелчке по методу left_btn в view2 он выдает сигнал, называемый «оставить». И я подключаю этот сигнал к лямбда-функции, чтобы удалить 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, или все еще есть некоторые события внутри view2 доступа к очереди событий после вызова deletelater ()?

Я загрузил всю свою программу (созданную с помощью QT creator) в github , если это поможет.

1 Ответ

0 голосов
/ 29 апреля 2018

Вы должны передать указатель view2, а не указатель указателя, кроме того, this не нужно.

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

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

Или просто не используйте лямбда-функцию, но новый стиль подключения :

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);
}
...