Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: notnext от Июнь 30, 2009, 08:13



Название: Проблема при вызове метода clear() у QGraphicsScene по сигналу
Отправлено: notnext от Июнь 30, 2009, 08:13
При вызове метода clear() у QGraphicsScene по сигналу QGraphicsProxyWidget приложение падает!
Как избежать падения приложения?

Вот пример кода:
Код
C++ (Qt)
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsProxyWidget>
#include <QPushButton>
 
int main(int argc, char *argv[]) {
   QApplication app(argc, argv);
 
   QGraphicsScene *scene = new QGraphicsScene();
 
   QGraphicsView *view = new QGraphicsView();
   view->setDragMode(QGraphicsView::ScrollHandDrag);
   view->setRenderHint(QPainter::Antialiasing, true);
   view->setSceneRect(-200, -200, 400, 400);
   view->setScene(scene);
   view->show();
 
   QPushButton *button = new QPushButton("TEST BUTTON", NULL);
   QObject::connect(button, SIGNAL(clicked()), scene, SLOT(clear()));
 
   QGraphicsProxyWidget *gWidget = scene->addWidget(button);
 
   scene->setSceneRect(scene->itemsBoundingRect());
 
   return app.exec();
}
 


Название: Re: Проблема при вызове метода clear() у QGraphicsScene по сигналу
Отправлено: notnext от Июнь 30, 2009, 11:00
Заранее спасибо тому, кто подскажет как это побороть!!!


Название: Re: Проблема при вызове метода clear() у QGraphicsScene по сигнаl
Отправлено: Rcus от Июнь 30, 2009, 11:28
Да, проблема есть (можно почитать ./src/gui/graphicsview/qgraphicsproxywidget.cpp : ~QGraphicsProxyWidget())
Борятся обычно при помощи своего слота, в котором используют QTimer::singleShot(0, scene, SLOT(clear()));

UPD: Хотя если не нужно ничего делать перед очисткой сцены можно попробовать просто связать через Qt::QueuedConnection


Название: Re: Проблема при вызове метода clear() у QGraphicsScene по сигнаl
Отправлено: notnext от Июль 01, 2009, 07:23
Да, проблема есть (можно почитать ./src/gui/graphicsview/qgraphicsproxywidget.cpp : ~QGraphicsProxyWidget())
Борятся обычно при помощи своего слота, в котором используют QTimer::singleShot(0, scene, SLOT(clear()));

UPD: Хотя если не нужно ничего делать перед очисткой сцены можно попробовать просто связать через Qt::QueuedConnection

QTimer::singleShot(0, scene, SLOT(clear())); Мне не очень подходит. :( Так как после очистки мне необходимо заполнить сцену другими QGraphicsItem. (Динамически простраиваемый GUI)

А вот как реализовать очистку сцены с помощью Qt::QueuedConnection интересно!
Если можно примерчик. Заранее благодарен!


Название: Re: Проблема при вызове метода clear() у QGraphicsScene по сигнаl
Отправлено: Rcus от Июль 01, 2009, 07:47
Эх, для того чтобы решить проблему надо понять ее. При обработке сигнала нельзя удалять emitter (вызывающий объект), но именно это и происходит при прямом соединении clicked() и clear() (обычно используется deleteLater(), что откладывает удаление до возврата в петлю). QTimer::singleShot(0..) это общая практика решения такой проблемы путем постановки действия в очередь.
Можно попробовать решить источник проблемы (я его уже указал), заменив оператор delete на метод отложенного удаления, но недостаток данного решения в том что оно может не сработать (честно я даже не пытался), ну и проблемы с распространением данного фикса по дистрибутивам, если вам это интересно (в Ubuntu 9.04 все еще 4.5.0, из-за чего плазма падает при установке нулевого размера панели)

ADD: Не совсем понятно как вы собрались вызывать код перестроения интерфейса если сигнал clicked() связан только со слотом clear().


Название: Re: Проблема при вызове метода clear() у QGraphicsScene по сигнаl
Отправлено: notnext от Июль 01, 2009, 08:17
ADD: Не совсем понятно как вы собрались вызывать код перестроения интерфейса если сигнал clicked() связан только со слотом clear().

На самом деле это просто ярко демонстрирующий пример ситуации.

В реальном проекте иерархия примерно такова:
    В сцена размещаются QGraphicsProxyWidget's (QPushButton, QComboBox ...)
    По какому либо  событию (действие пользователя, к примеру нажатие на QPushButton) вызывается определенный слот     размещающий опять же QGraphicsProxyWidget's.
    И в некоторых ситуациях необходимо полностью очистить сцену перед размещение новых Items.


Название: Re: Проблема при вызове метода clear() у QGraphicsScene по сигналу
Отправлено: mal от Июль 01, 2009, 10:48
Убей все ручками.

Код:
QList<QGraphicsItem *> items () const
// и в цикле по списку
 QGraphicsScene::removeItem ( QGraphicsItem * item )
deleteitem

Дедовский метод - но работает стопудово :-)