Как показать окно в Qt и удалить его, как только оно будет закрыто?

В качестве очень простого примера я хочу показать диалог в Qt, когда я нажимаю кнопку. Обычный шаблон для этого (в приложении, над которым я сейчас работаю), выглядит следующим образом:

class MainWindow {
  ...
private slots:
  buttonClicked();
  ...
private:
  ChildWindow * childWindow;
}

MainWindow::MainWindow(QWidget * parent) : QWidget(parent) {
  ...
  childWindow = new ChildWindow(this);
  ...
}

MainWindow::buttonClicked() {
  childWindow.show();
}

Исходя из .NET и Windows Forms (и поскольку мне не нужен доступ к этому объекту из других частей класса), мне более знаком следующий шаблон:

button1_Clicked(object sender, EventArgs e) {
  ChildWindow f = new ChildWindow();
  f.Show();
}

Локальная переменная означает, что у меня нет еще одного поля экземпляра, а также то, что окно не будет задерживаться в памяти намного дольше, чем необходимо. Прямой перевод этого на C++ был бы немного уродливым, потому что потом никто бы не разобрался. Я пробовал следующие вещи:

  1. shared_ptr. Не повезло, окно становится deleted, как только метод завершается, что означает, что новое окно появляется на долю секунды и снова исчезает. Не так хорошо, как хотелось бы.

  2. exec() вместо show(). Это будет работать для модальных диалогов, но документация, похоже, подразумевает, что это также останавливает цикл событий и что вы должны регулярно вызывать QApplication::processEvents(), если его все еще нужно обновить. Я понимаю здесь достаточно мало, но, думаю, это тоже не слишком приятно.

  3. deleteLater(). К сожалению, просто показ окна не блокирует deleteLater, поэтому оно исчезает, как только появляется.

Есть ли хороший вариант просто убрать за окном, когда я его закрываю?


person Joey    schedule 04.04.2013    source источник


Ответы (2)


childWindow->setAttribute( Qt::WA_DeleteOnClose );

Также обратите внимание, что вызов exec() заблокирует выполнение вызывающего цикла событий, но создаст собственный цикл событий, поэтому никаких вызовов processEvents() не требуется.

person Chris    schedule 04.04.2013
comment
Я не смог найти этот совет для exec снова нигде в документах, возможно, он просто был в каком-то случайном блоге сомнительной ценности. И спасибо за атрибут. Я искал по крайней мере час (+ время сборки для экспериментов), пока не наткнулся на идею просто подключить сигнал finished (что было не оптимально, но достаточно для моей цели). - person Joey; 04.04.2013
comment
На самом деле это довольно четко задокументировано в этом файле .cpp qt.gitorious.org/qt/qt/blobs/4.8/src/gui/dialogs/ ;) - person Chris; 04.04.2013
comment
Я имел в виду то, что я написал в вопросе о processEvents. То, что exec останавливает родительский цикл событий, довольно очевидно, потому что оно блокирует; также, что он должен создать новый для диалога. - person Joey; 04.04.2013

Вы можете подключить сигнал finished() этого диалога к его слоту deleteLater:

ChildWindow * d = new ChildWindow(this);
connect(d, SIGNAL(finished(int)), d, SLOT(deleteLater()));
d->show();

Таким образом, это будет deleted, как только вы закроете диалог.

person Joey    schedule 04.04.2013
comment
Примечание. Это работает в том случае, когда результат диалога не требуется. Если вам все еще нужен аргумент от finished(), то я не знаю, что произойдет. Но для моей проблемы этого было достаточно. - person Joey; 04.04.2013