Что использовать в Qt close() или destroy()?

552 просмотра
0

Всем привет!
Подскажите что использовать для закрытия окон в Qt? Я использую сразу обе функции для полного закрытия окна
self.close() и self.destroy()
Почему я так делаю:
1) Я написал приложение в котором вызывается диалоговое окно, и при нажатии на кнопку строиться таблица из 1,000,000 элементов. Так вот если использовать просто close(), то при повторном вызове этого диалогового окна таблица остается заполненной!(То есть сохраняется старая заполненная таблица)
Из этого выходит второй пункт
2) При использовании только close(), память не освобождается. Таблица из 1,000,000 элементов остается в памяти.

При использовании self.close() и self.destroy() одновременно, таких проблем нет, поэтому я сейчас все окно закрываю таким способом.
Посвятите неуча пожалуйста, правильно ли я делаю?


Добавить комментарий

3 Answers

Python Опубликовано 14.12.2018
0

Выдержки из Qt Assistant:
Оригинал:

bool QWidget::close() Closes this widget. Returns true if the widget
was closed; otherwise returns false.

First it sends the widget a QCloseEvent. The widget is hidden if it
accepts the close event. If it ignores the event, nothing happens. The
default implementation of QWidget::closeEvent() accepts the close
event.

If the widget has the Qt::WA_DeleteOnClose flag, the widget is also
deleted. A close events is delivered to the widget no matter if the
widget is visible or not.

The QApplication::lastWindowClosed() signal is emitted when the last
visible primary window (i.e. window with no parent) with the
Qt::WA_QuitOnClose attribute set is closed. By default this attribute
is set for all widgets except transient windows such as splash
screens, tool windows, and popup menus.

Перевод:

Закрывает этот виджет. Возвращает true, если этот виджет был закрыт;
иначе false.

Сначала посылается в QCloseEvent. Виджет скрывается если это событие
разрешается. Если нет, тот ничего не происходит. По умолчанию
наследование от QWidget::closeEvent() разрешает закрывающее событие.

Если виджет имеет Qt::WA_DeleteOnClose флаг(Примечание от меня,
задавать через
setAttribute(), например, this->setAttribute(Qt::WA_DeleteOnClose)), то он ещё и будет удалён.
Событие закрытия не доставляется в виджет в не зависимости от его
видимости.

Сигнал QApplication::lastWindowClosed() будет произведён, когда
последнее видимое главное окно(т.е. окно без родителя), с
установленным атрибутом Qt::WA_QuitOnClose, было закрыто. По
умолчанию этот атрибут установлен для всех виджетов, кроме
переходных(временных окон) таких, как частички на экране, оконные
инструменты и всплывающие меню.

Оригинал:

void QWidget::destroy(bool destroyWindow = true, bool
destroySubWindows = true) Frees up window system resources. Destroys
the widget window if destroyWindow is true.

destroy() calls itself recursively for all the child widgets, passing
destroySubWindows for the destroyWindow parameter. To have more
control over destruction of subwidgets, destroy subwidgets selectively
first.

This function is usually called from the QWidget destructor.

Перевод:

Освобождает окно системных ресурсов. Вызывает конструктор виджета
окна, если параметр destroyWindow равен true. destroy() вызывает
себя рекурсивно для всех дочерних виджетов, проходя
destroySubWindows для параметра destroyWindow. Для того, чтобы
иметь более гибкое управление нужно разрушить «подвиджеты» раньше.

Эта функция обычно вызывается в QWidget деструкторе.

Заранее извиняюсь за вольный перевод, старался наиболее правильно перевести.

Добавить комментарий
0

Читаем документацию к QWidget:

Closes this widget. Returns true if the widget was closed; otherwise
returns false.

Как можно заметить, здесь ничего не говорится об освобождении памяти, занимаемой объектом QWidget.

Не могу сказать, как точно работает менеджер памяти в python, приведу код на c++:

void foo()
{
  QWidget w;
  w.show();
  ....
  w.close();
}
 
void bar()
{
  QWidget* pw = new QWidget();
  w->show();
  ....
  w->close();
}

Пояснения:

Функция foo():

  • создаёт объект класса QWidget,
  • показывает окно,
  • делает что-то ещё…,
  • закрывает окно,
  • объект w уничтожается при выходе из области видимости, память отведённая для него освобождается.

Функция bar():

  • создаёт объект класса QWidget в динамической памяти,
  • показывает окно,
  • делает что-то ещё…,
  • закрывает окно,
  • объект *pw не уничтожается, а память им занимаемая не освобождается, т.к. программист намеренно не вызывает оператор delete.
Добавить комментарий
0

QDialog не реализует свой метод close, стало быть смотрим в базовом:

bool QWidget::close () [slot]

Closes this widget. Returns true if the widget was closed; otherwise returns false.

First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.

If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted. A close events is delivered to the widget no matter if the widget is visible or not.

The QApplication::lastWindowClosed() signal is emitted when the last visible primary window (i.e. window with no parent) with the Qt::WA_QuitOnClose attribute set is closed. By default this attribute is set for all widgets except transient windows such as splash screens, tool windows, and popup menus.

Т. е. при вызове close экземпляр окна может быть уничтожен, если выставлен флаг Qt::WA_DeleteOnClose.

Но можно вовсе не использовать ни close, ни destroy, а только создание экземпляра на стеке, вместо поля класса, как похоже, делает автор вопроса.

Я, обычно для модальных диалогов создаю небольшой класс с функцией getResult:

class MyTableDialog(QtGui.QDialog, ):
  __ui = None
  def __init__(self, parent):
    super(MyTableDialog, self).__init__(parent)
    ui = self.__ui = Ui_MyTableDialog()
    ui.setupUi(self)
    self.__my_setup_ui()
 
  def GetResult(self, *args, **kwds):
    self.__set_args_to_ui(*args, **kwds)
    if self.exec_() != self.Accepted:
      return
    return self.__get_res_from_ui()
 
  def __my_setup_ui(self):
    "Здесь дополнительно инициализируем интерфейс и связываем сигналы"
  def __set_args_to_ui(self, *args, **kwds):
    "Здесь устанавливаем данные в элементы интерфейса"
  def __get_res_from_ui(self):
    "Здесь вытаскиваем введённые в интерфейсе данные"
 
# Пример использования
class MyMainWindow(...):
  def GetUserTable(self, *args, **kwds):
    res = MyTableDialog(self).GetResult(*args, **kwds)
    if res is None:
      logging.info('Пользователь отказался от ввода')
    else:
      self.__parse_user_table_input(res)

Добавить комментарий
Напишите свой ответ на данный вопрос.
Scroll Up