Results 1 to 6 of 6

Thread: Crash using QGraphicsEffect with QGraphicsItemGroup

  1. #1
    Join Date
    Feb 2007
    Location
    Italy
    Posts
    69
    Thanks
    12
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Crash using QGraphicsEffect with QGraphicsItemGroup

    Hello,
    I'm experiencing a crash when, after applying a graphic effect on an item group, I try to remove from the scene that item group. The crash doesn't happen if I apply the effect to items of the group or if I don't use the effect at all.

    I'm trying to create a scene with some items (with effect), and when a key is pressed, only a part of such items are deleted. I wrote this little demo (see below). Running it, I do some random clicks and press Escape. The application crash (SIGSEGV) on line 135 of qscopedpointer.h, function data.

    Please, tell me if I'm doing something wrong or test if it works on your implementation, I'm using Qt 4.7.3 (64 bit).

    Here's the code (removed the guards from the headers).

    main.cpp
    Qt Code:
    1. #include <QtGui/QApplication>
    2. #include "mainwindow.hh"
    3.  
    4. int main(int argc, char *argv[]) {
    5. QApplication a(argc, argv);
    6. MainWindow w;
    7. w.show();
    8. return a.exec();
    9. }
    To copy to clipboard, switch view to plain text mode 

    itemfieldeffect.hh
    Qt Code:
    1. #include <QtGui>
    2.  
    3. class ItemFieldEffect: public QGraphicsEffect {
    4. public:
    5. ItemFieldEffect(qreal radius);
    6. void draw(QPainter *painter);
    7. QRectF boundingRectFor(const QRectF &sourceRect) const;
    8. private:
    9. qreal _radius;
    10. };
    To copy to clipboard, switch view to plain text mode 

    itemfieldeffect.cpp
    Qt Code:
    1. #include "itemfieldeffect.hh"
    2.  
    3. ItemFieldEffect::ItemFieldEffect(qreal radius):
    4. _radius(radius) {
    5. }
    6.  
    7. void ItemFieldEffect::draw(QPainter *painter) {
    8. painter->save();
    9. QRadialGradient grad(0, 0, _radius);
    10. grad.setSpread(QGradient::PadSpread);
    11. grad.setColorAt(0, QColor(0, 0, 0, 200));
    12. grad.setColorAt(1.0, QColor(0, 0, 0, 30));
    13. painter->setBrush(QBrush(grad));
    14. painter->setPen(Qt::NoPen);
    15. painter->drawEllipse(-_radius, -_radius, _radius * 2, _radius * 2);
    16. painter->restore();
    17. drawSource(painter);
    18. }
    19.  
    20. QRectF ItemFieldEffect::boundingRectFor(const QRectF &sourceRect) const {
    21. return sourceRect.adjusted(-_radius, -_radius, _radius, _radius);
    22. }
    To copy to clipboard, switch view to plain text mode 

    mainwindow.hh
    Qt Code:
    1. #include <QtGui>
    2.  
    3. class MainWindow: public QMainWindow {
    4. Q_OBJECT
    5. public:
    6. MainWindow(QWidget *parent = 0);
    7. bool eventFilter(QObject *target, QEvent *event);
    8. QGraphicsItem *createPoint(const QPointF &pos, const QString &label);
    9. private:
    10. QMap<QString, QGraphicsItem *> _visiblePoints;
    11.  
    12. };
    To copy to clipboard, switch view to plain text mode 

    mainwindow.cpp
    Qt Code:
    1. #include "mainwindow.hh"
    2. #include "itemfieldeffect.hh"
    3.  
    4. MainWindow::MainWindow(QWidget *parent)
    5. : QMainWindow(parent) {
    6. _gv = new QGraphicsView(this);
    7. setCentralWidget(_gv);
    8. _gs = new QGraphicsScene(this);
    9. _gv->setScene(_gs);
    10. _gv->installEventFilter(this);
    11. }
    12.  
    13. QGraphicsItem *MainWindow::createPoint(const QPointF &pos, const QString &label) {
    14. grp->setFlags(QGraphicsItem::ItemIsSelectable);
    15. bg->setBrush(QColor::fromRgb(255, 244, 194, 220));
    16. lab->setPlainText(label);
    17. bg->setRect(lab->boundingRect());
    18. qreal x = bg->rect().width() / -2.0;
    19. qreal y = bg->rect().height() / -2.0;
    20. bg->setPos(x, y);
    21. lab->setPos(x, y);
    22. grp->setPos(pos);
    23. grp->setGraphicsEffect(new ItemFieldEffect(50));
    24. return grp;
    25. }
    26.  
    27. bool MainWindow::eventFilter(QObject *target, QEvent *event) {
    28. if (target == _gv) {
    29. switch (event->type()) {
    30. case QEvent::Resize: {
    31. QResizeEvent *re = static_cast<QResizeEvent *>(event);
    32. _gv->setSceneRect(0, 0, re->size().width(), re->size().height());
    33. break;
    34. }
    35. case QEvent::MouseButtonPress: {
    36. QMouseEvent *me = static_cast<QMouseEvent *>(event);
    37. QPointF pos = me->posF();
    38. static int counter = 0;
    39. QString id = QString("%1").arg(++counter);
    40. QGraphicsItem *it = createPoint(pos, id);
    41. _gs->addItem(it);
    42. if (counter % 2)
    43. _visiblePoints.insert(id, it);
    44. break;
    45. }
    46. case QEvent::KeyPress: {
    47. QKeyEvent *ke = static_cast<QKeyEvent *>(event);
    48. if (ke->key() == Qt::Key_Escape) {
    49. foreach (QString id, _visiblePoints.keys())
    50. _gs->removeItem(_visiblePoints.value(id));
    51. _visiblePoints.clear();
    52. }
    53. break;
    54. }
    55. default: { }
    56. }
    57. }
    58. return false;
    59. }
    To copy to clipboard, switch view to plain text mode 

    Any feedback appreciated.
    Thanks
    ~Aki

  2. #2
    Join Date
    Dec 2009
    Posts
    128
    Thanks
    7
    Thanked 14 Times in 14 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Crash using QGraphicsEffect with QGraphicsItemGroup

    I reproduce on WinXP 32 bits Qt 4.7.0
    Problem comes from a call to ItemFieldEffect::draw() from event loop, while associated scene pointer of the effect is null. This triggers a Q_ASSERT() in QGraphicsItemEffectSourcePrivate::draw()

    If I unset the graphics effect pointer before removing the item from the scene, crash disappears :

    Qt Code:
    1. bool MainWindow::eventFilter(QObject *target, QEvent *event) {
    2. if (target == _gv) {
    3. switch (event->type())
    4. {
    5. // ... other events
    6.  
    7. case QEvent::KeyPress:
    8. {
    9. QKeyEvent *ke = static_cast<QKeyEvent *>(event);
    10. if (ke->key() == Qt::Key_Escape)
    11. {
    12. foreach (QGraphicsItem *item, _visiblePoints.values())
    13. {
    14. item->setGraphicsEffect(0) ; // HERE
    15. _gs->removeItem(item);
    16. }
    17. _visiblePoints.clear();
    18. }
    19. break;
    20. }
    21. default: { }
    22. }
    23. }
    24. return false;
    25. }
    To copy to clipboard, switch view to plain text mode 

    For me, a test is missing somewhere in Qt code to make sure the scene pointer of the QGraphicsEffect object is reliable (at least not null!) before a call to its draw() method.

  3. The following user says thank you to totem for this useful post:

    akiross (16th August 2011)

  4. #3
    Join Date
    Feb 2007
    Location
    Italy
    Posts
    69
    Thanks
    12
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Crash using QGraphicsEffect with QGraphicsItemGroup

    Ok, thanks for the feedback. I'm sending a feedback to nokia's bugzilla.

  5. #4
    Join Date
    Feb 2007
    Location
    Italy
    Posts
    69
    Thanks
    12
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Crash using QGraphicsEffect with QGraphicsItemGroup

    Excuse me if I change sightly the topic, but I've another issue here that may be related to this (bug?):
    I did as you suggested, resetting the effect before removal, and now it doesn't crash, but even if effects are removed, some items are still visible on the scene. Note that they are removed, but they seems to be buffered and are still painted.
    Invalidating or updating the scene didn't help, but if I add new items after removing them, the repaint seems to work.
    In other words, try this sequence (or similar): random clicks -> escape -> random clicks elsewhere -> repaint window -> old items are removed.

    I had to hack it setting items invisible before removal:
    Qt Code:
    1. foreach (QString id, _visiblePoints.keys()) {
    2. _visiblePoints.value(id)->setGraphicsEffect(0);
    3. _visiblePoints.value(id)->setVisible(false); // This
    4. _gs->removeItem(_visiblePoints.value(id));
    5. }
    To copy to clipboard, switch view to plain text mode 

    And seems to clear correctly in every case.
    ~Aki

  6. #5
    Join Date
    Dec 2009
    Posts
    128
    Thanks
    7
    Thanked 14 Times in 14 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Crash using QGraphicsEffect with QGraphicsItemGroup

    Isn't it because of this ?

    Qt Code:
    1. if (counter % 2)
    2. _visiblePoints.insert(id, it);
    To copy to clipboard, switch view to plain text mode 

    you only save 1 pointer on 2.
    try without that if statement; and insert graphicsItem each time you create them ?

  7. #6
    Join Date
    Feb 2007
    Location
    Italy
    Posts
    69
    Thanks
    12
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Crash using QGraphicsEffect with QGraphicsItemGroup

    No no, I was talking about the removed items... I tried to remove that condition anyway, but the problem persists. Also, I experienced successfully the field effect removal, but the item itself was not correctly cleaned.

Similar Threads

  1. QGraphicsEffect on a Phonon::VideoPlayer
    By scary_jeff in forum Newbie
    Replies: 3
    Last Post: 20th January 2011, 01:12
  2. problem in QGraphicsItemGroup
    By wagmare in forum Qt Programming
    Replies: 1
    Last Post: 14th May 2009, 08:27
  3. mouseDoubleClickEvent in QGraphicsItemGroup
    By dima in forum Qt Programming
    Replies: 0
    Last Post: 9th March 2009, 07:01
  4. Add two QGraphicsItemGroup
    By ashishsaryar in forum Qt Programming
    Replies: 2
    Last Post: 5th February 2008, 18:00
  5. setZValue of QGraphicsItemGroup
    By forrestfsu in forum Qt Programming
    Replies: 3
    Last Post: 6th November 2006, 19:40

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.