Russian Qt Forum
Сентябрь 25, 2024, 10:30 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема при вызове метода clear() у QGraphicsScene по сигналу  (Прочитано 6258 раз)
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();
}
 
« Последнее редактирование: Июнь 30, 2009, 08:22 от notnext » Записан
notnext
Гость
« Ответ #1 : Июнь 30, 2009, 11:00 »

Заранее спасибо тому, кто подскажет как это побороть!!!
Записан
Rcus
Гость
« Ответ #2 : Июнь 30, 2009, 11:28 »

Да, проблема есть (можно почитать ./src/gui/graphicsview/qgraphicsproxywidget.cpp : ~QGraphicsProxyWidget())
Борятся обычно при помощи своего слота, в котором используют QTimer::singleShot(0, scene, SLOT(clear()));

UPD: Хотя если не нужно ничего делать перед очисткой сцены можно попробовать просто связать через Qt::QueuedConnection
« Последнее редактирование: Июнь 30, 2009, 19:09 от Rcus » Записан
notnext
Гость
« Ответ #3 : Июль 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 интересно!
Если можно примерчик. Заранее благодарен!
Записан
Rcus
Гость
« Ответ #4 : Июль 01, 2009, 07:47 »

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

ADD: Не совсем понятно как вы собрались вызывать код перестроения интерфейса если сигнал clicked() связан только со слотом clear().
« Последнее редактирование: Июль 01, 2009, 07:53 от Rcus » Записан
notnext
Гость
« Ответ #5 : Июль 01, 2009, 08:17 »

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

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

В реальном проекте иерархия примерно такова:
    В сцена размещаются QGraphicsProxyWidget's (QPushButton, QComboBox ...)
    По какому либо  событию (действие пользователя, к примеру нажатие на QPushButton) вызывается определенный слот     размещающий опять же QGraphicsProxyWidget's.
    И в некоторых ситуациях необходимо полностью очистить сцену перед размещение новых Items.
Записан
mal
Гость
« Ответ #6 : Июль 01, 2009, 10:48 »

Убей все ручками.

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

Дедовский метод - но работает стопудово :-)
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.131 секунд. Запросов: 21.