Вызов деструктора Qt для закрытого виджета - PullRequest
8 голосов
/ 17 августа 2011

Есть приложение, которое обрабатывает текстовые команды.У меня есть виджет Qt, который закрывается какой-то командой close *.Qt::WA_DeleteOnClose Атрибут установлен для этого виджета, он получает closeEvent, но деструктор для этого объекта вызывается позже (я думаю, на холостом ходу).Если у меня есть две команды close *; get something;, программа падает, потому что get something вызывается перед деструктором для этого виджета, поэтому она пытается получить доступ к данным, удаленным командой close *.Как я могу заставить Qt вызывать деструкторы?QCoreApplication::processEvents() после команды закрытия не помогает.У меня возникла эта проблема после изменения версии qt с 4.3.3 на 4.7.2.Здесь нет многопоточности.

Заранее спасибо.

добавлено

Вот пример кода.

test *t = new test();
t->show();
std::cout << "before deleteLater()" << std::endl;
t->deleteLater();
std::cout << "after deleteLater()" << std::endl;
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();
std::cout << "after processEvents()" << std::endl;

Тестовый класс является производным от QDialog.Он печатает test() в конструкторе и ~test() в деструкторе.Этот код дает следующий вывод

test()
before deleteLater()
after deleteLater()
after processEvents()
~test()

В соответствии с документацией Qt он должен удалить объект до последнего вызова, я прав?Похоже на ошибку в Qt, кто-нибудь знает что-нибудь об этом?Есть ли обходной путь?

Я задал вопрос в списке рассылки Qt, но все еще жду ответа.

Спасибо.

еще одно обновление

Этот код

Dialog::~Dialog() {
    std::cout << "~test()" << std::endl;
}

int main(int argc, char* argv[]) {
    QApplication app(argc, argv);
    Dialog* dlg = new Dialog();
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->show();
    dlg->close();
    std::cout << "before sendPostedEvents()" << std::endl;
    QCoreApplication::sendPostedEvents();
    std::cout << "after sendPostedEvents()" << std::endl;
    return app.exec();
}

печатает этот

before sendPostedEvents()
after sendPostedEvents()
~test()

, но как только я добавляю обработчик closeEvent и вызываю deleteLater () в этой функции-обработчике sendPostedEvents начинает удалять отложенные объекты.

void Dialog::closeEvent(QCloseEvent* ev) {
    deleteLater();
    QWidget::closeEvent(ev);
}

печатает это перед sendPostedEvents () ~ test () после sendPostedEvents ()

Кто-нибудь может объяснить, что, черт возьми, там происходит?Это просто ошибка?Могу ли я использовать это в качестве обходного пути?

Как это работает?Разве Qt не должен вызывать deleteLater () автоматически после того, как closeEvent принят, если установлен атрибут CloseOnDelete?

Ответы [ 2 ]

7 голосов
/ 17 августа 2011

Настройка Qt::WA_DeleteOnClose означает, что qt может удалить в любое время после того, как вы позвоните close(), потому что qt использует deleteLater() для внутреннего использования.Вы можете обеспечить удаление, используя сигнал QObject::destroyed().

1 голос
/ 10 декабря 2016

QCoreApplication :: processEvents явно пропускает удаление при событиях закрытия. Вам нужно передать QEventLoop :: DeferredDeletion в processEvents (). то есть QCoreApplication :: processEvents (QEventLoop :: DeferredDeletion);

...