Russian Qt Forum

Qt => Общие вопросы => Тема начата: QCasper от Февраль 27, 2007, 17:57



Название: Не удалять чайлды.
Отправлено: QCasper от Февраль 27, 2007, 17:57
У меня есть QDockWidget, я ему в определенный момент делаю setWidget(widget), потом во второй определенный момент я удаляю widget. И когда завершаю работу приложения, оно сваливается, насколько я понял из-за того что док виджет пытается удалить тот виджет, а там уже все инвалидно. Как пофиксить?


Название: Не удалять чайлды.
Отправлено: Mikhail от Февраль 27, 2007, 20:19
А кто у этого видгета parent?
В этом проблема.
Почему же QDockWidget должен удалять widget?
Скорее всего ты создаешь widget типа new MyWidget(this).
Вот this == parent и пытается в своем деструкторе по умолчанию удалить уже удаленныый widget.


Название: Не удалять чайлды.
Отправлено: QCasper от Февраль 27, 2007, 21:13
Цитата: "Mikhail"
А кто у этого видгета parent?
В этом проблема.
Почему же QDockWidget должен удалять widget?
Скорее всего ты создаешь widget типа new MyWidget(this).
Вот this == parent и пытается в своем деструкторе по умолчанию удалить уже удаленныый widget.


А я разве спорю? Парент у этого виджета - док виджет, он его и пытается удалить, я вроде так и написал. Вопрос не в том че за фигня, а в том как сделать чтобы этого не происходило. Как сделат чтобы парент не удалял этот виджет, даже не пытался. Если я что-то непонятное говорю, то вот код:

Код:
QDockWidget *dock = new QDockWidget;
QWidget *widget = new QWidget(dock);
dock->setWidget(widget);


После всего этого, widget в определенный момент удаляется. И соотвественно приложение падает когда деструктор доквиджета пытается замочить этот виджет.


Название: Не удалять чайлды.
Отправлено: Lion от Февраль 27, 2007, 21:37
widget->setParent(0) перед удалением.


Название: Не удалять чайлды.
Отправлено: QCasper от Февраль 27, 2007, 22:13
Цитата: "Lion"
widget->setParent(0) перед удалением.


Че-то не помогло...


Название: Не удалять чайлды.
Отправлено: Вячеслав от Февраль 28, 2007, 08:14
Код:
 dock->setWidget(0);
а так ?


Название: Не удалять чайлды.
Отправлено: Mikhail от Февраль 28, 2007, 08:32
Попробуй
QDockWidget *dock = new QDockWidget;
QWidget *widget = new QWidget;
dock->setWidget(widget);
должно получиться.

В деструкторе, наверно приложения или mainwindow, проверь наличие ненулевого указателя на widget и в этом случае удали его с помощью delete.

добавлено спустя 52 секунды:

 Последнее предложение относится к случаю завершения приложения.


Название: Solved!
Отправлено: QCasper от Февраль 28, 2007, 12:55
Цитата: "Mikhail"
Попробуй
QDockWidget *dock = new QDockWidget;
QWidget *widget = new QWidget;
dock->setWidget(widget);
должно получиться.

В деструкторе, наверно приложения или mainwindow, проверь наличие ненулевого указателя на widget и в этом случае удали его с помощью delete.

добавлено спустя 52 секунды:

 Последнее предложение относится к случаю завершения приложения.


QWidget *widget = new QWidget; - этот момент меня не устравивает, потому что этот виджет должен знать кто ему парент, потому как он своему паренту определенные настройки передает.

добавлено спустя 1 час:

 Вот код. На самом деле указатель на виджет который потом устанавливается на доквиджет, я получаю из плагина. Так вот если выгрузить плагин, то приложение падает по завершению, если не выгружать, а просто удалить виджет (m_Plugin->deactivate()), то не падает.

Код:
MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
m_Dw = new QDockWidget(this);
addDockWidget(Qt::RightDockWidgetArea, m_Dw);

m_Loader = new QPluginLoader("ddoverlay.dll", this);
if (m_Plugin = qobject_cast<IRenderingPlugin*>(m_Loader->instance()))
{
if (QWidget *wg = m_Plugin->activate(m_Dw, QSize(720,576)))
m_Dw->setWidget(wg);
}
QPushButton *btn = new QPushButton(this);
connect(btn, SIGNAL(clicked()), this, SLOT(deactivate()));

setCentralWidget(btn);
}

MainWindow::~MainWindow()
{
}
void MainWindow::deactivate() {
if (m_Plugin) {
m_Plugin->deactivate();
m_Dw->setWidget(0);
m_Loader->unload();
}
}


добавлено спустя 1 час 12 минут:

 Все прояснилось - полностью мой косяк. Там в этом плагине я паренту еще инсталил эвент фильтер. И забыл его удалить. Вот, и после того как плагин выгружался, адрес терялся, а при уничтожении доквиджета, последний пытался грохнуть этот эвент фильтер.
И вообще, как выяснилось, на будующее, если вы где-то мочите собственноручно чайлда, то он автоматически удаляется из списка чилдренов родителя. Цитата из асистанта:
Цитировать
You can also delete child objects yourself, and they will remove themselves from their parents.

Поэтому предложения типа "перед удалением setParent(0)" изначально не имели бы никакого эфекта.