Results 1 to 13 of 13

Thread: When is the best time to delete a QCanvasItem

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Feb 2006
    Posts
    14
    Thanked 1 Time in 1 Post
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: When is the best time to delete a QCanvasItem

    Hi

    No the code is not multithreaded. In brief an explanation of the order code called
    1. A BGraphWgtBase_c (QCanvasItem) is deleted
    2. It marks itself for deletion.
    3. Qt passes overridden mouse type calls to my code; press, release and move
    4. The canvas deletes marked items
    5. My code then carries out the wishes of the uses for that pass.
    6. My code test for item collisions with the mouse
    7. Some canvas updates may take place.
    8. A crash may occur now.
    9. Mean while there is a canvas timer to update peridocially any items that have flaged to be updated.

    Qt Code:
    1. BGraphWgtBase_c::~BGraphWgtBase_c( void )
    2. {
    3. hide();
    4. DeleteChildren();
    5. }
    6.  
    7. //virtual
    8. bool BGraphWgtBase_c::Redraw()
    9. {
    10. QRect rectToRefresh( boundingRect() );
    11. m_pParent->setChanged( rectToRefresh );
    12. m_pParent->SetDoARedrawPlease();
    13.  
    14. return RDstatus::success;
    15. }
    16.  
    17. bool BGraphWgtBase_c::SetMarkForDelete()
    18. {
    19. m_bIsMarkedForDelete = true;
    20. hide();
    21.  
    22. // Now go through all this widget's child widgets and mark for delete too
    23. ListWgts::iterator it = m_listChildWidgets.begin();
    24. while( it != m_listChildWidgets.end() )
    25. {
    26. BGraphWgtBase_c * pWgt = *it;
    27. if( pWgt == NULL )
    28. {
    29. continue;
    30. }
    31. pWgt->hide();
    32. pWgt->SetMarkForDelete();
    33.  
    34. // Move to next
    35. ++it;
    36. }
    37.  
    38. return RDstatus::success;
    39. }
    40. // Slot
    41. // Visited every 500ms to do canvas updates
    42. void BGraphCanvas_c::SlotUpdateTimer()
    43. {
    44. if( m_bDoARedrawPlease )
    45. {
    46. m_bDoARedrawPlease = false;
    47.  
    48. try
    49. {
    50. update();
    51. }
    52. catch( ... )
    53. {
    54.  
    55. }
    56. }
    57.  
    58. return;
    59. }
    60.  
    61. // Set by BGraphWgtBase_c to flag that at least one item on the canvas
    62. // would like to be updated
    63. bool BGraphCanvas_c::SetDoARedrawPlease()
    64. {
    65. m_bDoARedrawPlease = true;
    66. return RDstatus::success;
    67. }
    68.  
    69. // This function goes through all the widgets ( canvas items ) registered with this canvas
    70. // and deletes the items which have been marked for deletion. Widgets for this canvas class
    71. // operation do not get deleted at source when not needed as they may be still in use, or their
    72. // children still in use. They could be contained in the canvas's various containers at the
    73. // time they are deemed as not needed anymore. This function and the
    74. // BGraphWgtBase_c::SetMarkForDelete function enacts a delayed delete system. At the
    75. // source hide the widget and mark for delete. This function is called sometime later and will delete the
    76. // marked items. BGraphWgtBase_c::SetMarkForDelete function also at the same time informs the BGraphWgtMgr_c
    77. // of the widget's removal so it can update its records.
    78. // Note: Very important when this is called. For example do not call at end of
    79. // mouseReleaseEvent(). QCanvas does behind the scenes work
    80. // on all it canvas items after mouseReleaseEvent() and so deleting any before then
    81. // is not a good and causes a crash.
    82. bool BGraphCanvas_c::DeleteMarkedWgts()
    83. {
    84. BGraphWgtBase_c * pCurrentSelectedWgt = GetView()->GetCurrentSelectedItem();
    85. bool bDeleteWgt = false;
    86. QCanvasItemList listAllItems = allItems();
    87. QCanvasItemList::iterator it = listAllItems.begin();
    88. while( it != listAllItems.end() )
    89. {
    90. BGraphWgtBase_c * pWgt = dynamic_cast< BGraphWgtBase_c * >( *it );
    91. if( (pWgt != NULL) && pWgt->IsMarkForDelete() )
    92. {
    93. if( pWgt == pCurrentSelectedWgt )
    94. {
    95. GetView()->SetCurrentSelectedItem( NULL );
    96. }
    97.  
    98. delete pWgt;
    99. bDeleteWgt = true;
    100. }
    101.  
    102. // Next
    103. ++it;
    104. }
    105.  
    106. if( bDeleteWgt )
    107. {
    108. update();
    109. }
    110.  
    111. return RDstatus::success;
    112. }
    113.  
    114. QCanvasItemList BGraphCanvas_c::GetDlgsHitHoverOver( const QPoint & vMousePos )
    115. {
    116. QCanvasItemList wgtHoverOverHitList;
    117. QPoint realMousePos( GetRealX( vMousePos.x() ), GetRealY( vMousePos.y() ) );
    118. wgtHoverOverHitList = Collisions( realMousePos );
    119.  
    120. return wgtHoverOverHitList;
    121. }
    122.  
    123. //virtual
    124. void BGraphCanvas_c::update()
    125. {
    126. // The try catch is here to stop QCanvas crash if it comes
    127. // across an invalid pointer to a QCanvasItem. This is a bug which
    128. // has been difficult to solve as when is the right time to delete
    129. // a QCanvasItem. See DeleteWgts() in this class which is there to
    130. // try to stop this sort of thing happening.
    131. try
    132. {
    133. QCanvas::update();
    134. }
    135. catch( ... )
    136. {
    137. ;
    138. }
    139. }
    140.  
    141. QCanvasItemList BGraphCanvas_c::Collisions( const QPoint & vMousePos )
    142. {
    143. try
    144. {
    145. return collisions( vMousePos );
    146. }
    147. catch( ... )
    148. {
    149. ;
    150. }
    151.  
    152. QCanvasItemList list;
    153. return list;
    154. }
    155.  
    156. // vpWgtExceptThisOne would normally be the current selected widget
    157. const RDstr BGraphCanvas_c::GetDlgHitHoverOver( const QPoint & vMousePos, BGraphWgtBase_c * vpWgtExceptThisOne )
    158. {
    159. RDstr dlgId;
    160.  
    161. if( !IsOnCanvas( vMousePos ) )
    162. {
    163. return dlgId;
    164. }
    165.  
    166. QPoint realMousePos( GetRealX( vMousePos.x() ), GetRealY( vMousePos.y() ) );
    167. QCanvasItemList listDlgHitByMouse = Collisions( realMousePos );
    168.  
    169. // User clicked on a widget that recognised itself as hitable/selectable
    170. dlgId = pDlgItem->GetId();
    171.  
    172. return dlgId;
    173. }
    174.  
    175. // return: valid id or no id = no hit
    176. const RDstr BGraphCanvas_c::GetDlgHit( const QPoint & vMousePos, BGraphWgtBase_c * vpWgtExceptThisOne )
    177. {
    178. return GetDlgHitHoverOver( vMousePos, vpWgtExceptThisOne );
    179. }
    180.  
    181.  
    182.  
    183. bool BGraphCanvas_c::IsThisWidgetHit( const QPoint & vPosMouse, const RDstr & vWidgetId )
    184. {
    185. bool bHaveHitSpecificWidget = false;
    186.  
    187. QCanvasItemList listHitItems = GetDlgsHitHoverOver( vPosMouse );
    188.  
    189. return bHaveHitSpecificWidget;
    190. }
    191.  
    192. void BGraphCanvasView_c::mousePressEvent( QMouseEvent * vpEvent )
    193. {
    194. // Clean out widgets marked for deletion. Very important this is called here
    195. // and not say on mouseReleaseEvent(). QCanvas does behind the scenes work
    196. // on all it canvas items after mouseReleaseEvent() and so deleting any before then
    197. // is not a good and causes a crash.
    198. m_pGraphAreaCanvas->DeleteMarkedWgts();
    199.  
    200. // Has user clicked on an canvas area dialog (QCanvasItem )
    201. m_mouseButtonPressCursorPos = viewportToContents( vpEvent->pos() );
    202.  
    203. m_currentSelectedAreaDlgId = m_pGraphAreaCanvas->GetDlgHit( m_mouseButtonPressCursorPos, NULL );
    204. m_pCurrentSelectedWgt = m_pGraphAreaCanvas->GetDlgObj( m_currentSelectedAreaDlgId );
    205. if( NULL == m_pCurrentSelectedWgt )
    206. {
    207. // Reset all widget depths accept the current selected widget
    208. m_pAGraph->GetGraphCanvasWgtMgr()->WgtsSetAllToNominalAreaZDepth( NULL );
    209. return;
    210. }
    211.  
    212. // Create store for event into to be passed onto all hit widgets (canvas items)
    213. BGraphWgtEventInfo_s sEventInfo;
    214.  
    215. // Pass event onto selected widget (canvas item)
    216. if( m_pCurrentSelectedWgt->MousePressEvent( sEventInfo ) )
    217. {
    218. // Inform the client using BPkgGraph that possible item valid for selection is selected
    219. m_pAGraph->SetCurrentlySelectedWidgetId( m_pCurrentSelectedWgt->GetId() );
    220. }
    221.  
    222. // Pass event onto rest of hit widgets. These are not the most forward Z pos
    223. // widgets.
    224. m_pGraphAreaCanvas->MousePressEvent( sEventInfo );
    225.  
    226. // Reset all widget depths accept the current selected widget
    227. m_pAGraph->GetGraphCanvasWgtMgr()->WgtsSetAllToNominalAreaZDepth( m_pCurrentSelectedWgt );
    228. }
    229.  
    230. void BGraphCanvasView_c::mouseReleaseEvent( QMouseEvent * vpEvent )
    231. {
    232. // Create store for event into to be passed onto all hit widgets (canvas items)
    233.  
    234. if( NULL != m_pCurrentSelectedWgt )
    235. {
    236. // Pass event onto selected widget (canvas item)
    237. m_pCurrentSelectedWgt->MouseReleaseEvent( sEventInfo );
    238. }
    239.  
    240. // Pass event onto rest of hit widgets. These are not the most forward Z pos
    241. // widgets.
    242. m_pGraphAreaCanvas->MouseReleaseEvent( sEventInfo );
    243.  
    244. // Reset all widget depths accept the last selected widget
    245. m_pAGraph->GetGraphCanvasWgtMgr()->WgtsSetAllToNominalAreaZDepth( m_pCurrentSelectedWgt );
    246. }
    247.  
    248.  
    249. void BGraphCanvasView_c::contentsMouseMoveEvent( QMouseEvent * vpEvent )
    250. {
    251. // Create store for event into to be passed onto all hit widgets (canvas items)
    252.  
    253. // User clicked on an canvas area dialog (QCanvasItem )
    254. if( m_bMouseLeftButtonHitAreaDlg && m_bMouseLeftButtonDown )
    255. {
    256. // to use this m_currentSelectedAreaDlgId
    257. if( NULL != m_pCurrentSelectedWgt )
    258. {
    259. // Pass event onto selected widget (canvas item)
    260. m_pCurrentSelectedWgt->MouseContentMoveEvent( sEventInfo );
    261. }
    262. }
    263.  
    264. // Pass event onto rest of hit widgets. These are not the most forward Z pos
    265. // widgets.
    266. m_pGraphAreaCanvas->MouseContentMoveEvent( sEventInfo );
    267.  
    268. // User just moving the mouse over the canvas. Highlight most forward hit widget if any.
    269. // Unhighlight previous widget if it still exists
    270. // Turn off all/any highlighted hit widget areas
    271. QPoint mousePos( vpEvent->pos() );
    272. const RDstr wgtId = m_pGraphAreaCanvas->GetDlgHitHoverOver( mousePos, pWgtExceptThisOne );
    273.  
    274. // Crash in collisions in GetDlgHitHoverOver()
    275. // snip
    276. }
    277. }
    278.  
    279. // Update the view
    280. m_pGraphAreaCanvas->update();
    281. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: When is the best time to delete a QCanvasItem

    Note that canvas items are not widgets.

    Your code is quite complex -- it uses many variables and methods. Could you post a minimal compilable example which reproduces the problem?

  3. #3
    Join Date
    Jan 2006
    Location
    Athens - Greece
    Posts
    219
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: When is the best time to delete a QCanvasItem

    Or post a debugger backtrace to lead us somewhere...
    Anyway I'd also delete the item like:
    Qt Code:
    1. delete pWgt;
    2. pWgt = NULL;
    To copy to clipboard, switch view to plain text mode 
    I have the feeling that the qt "internals" would check for null pointers before using them (I know I do)

  4. #4
    Join Date
    Feb 2006
    Posts
    14
    Thanked 1 Time in 1 Post
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: When is the best time to delete a QCanvasItem

    Hi

    On Linux a can get the following back trace:

    Program received signal SIGSEGV, Segmentation fault.
    [Switching to Thread -150104960 (LWP 3629)]
    0xc31600d2 in ?? ()
    (gdb) bt
    #0 0xc31600d2 in ?? ()
    #1 0x0b0af5dd in ?? ()
    #2 0x00bde85d in QCanvasItemList::drawUnique (this=0xfee4a090,
    painter=@0xfee49f20) at canvas/qcanvas.cpp:349
    #3 0x00be25a2 in QCanvas::drawCanvasArea (this=0xafd1b00, inarea=@0xfee4a120,
    p=0x0, double_buffer=true) at canvas/qcanvas.cpp:1431
    #4 0x00be1f00 in QCanvas::drawChanges (this=0xafd1b00, inarea=@0xb10dac8)
    at canvas/qcanvas.cpp:1337
    #5 0x00be1516 in QCanvas::update (this=0xafd1b00) at canvas/qcanvas.cpp:1183
    #6 0x082dbd6b in BGraphCanvasView_c::contentsMouseMoveEvent (this=0xafd1ec0,
    vpEvent=0xfee4a510) at BPkgGraph/BGraphCanvasView.cpp:999
    #7 0x00ac629d in QScrollView::viewportMouseMoveEvent (this=0xafd1ec0,
    e=0xfee4a8a0) at widgets/qscrollview.cpp:1782
    #8 0x00ac5756 in QScrollView::eventFilter (this=0xafd1ec0, obj=0xa8144b0,
    e=0xfee4a8a0) at widgets/qscrollview.cpp:1512
    #9 0x00975967 in QObject::activate_filters (this=0xa8144b0, e=0xfee4a8a0)
    at kernel/qobject.cpp:902
    #10 0x009757d8 in QObject::event (this=0xa8144b0, e=0xfee4a8a0)
    at kernel/qobject.cpp:735
    #11 0x009bbca6 in QWidget::event (this=0xa8144b0, e=0xfee4a8a0)
    at kernel/qwidget.cpp:4655
    #12 0x0090a6f5 in QApplication::internalNotify (this=0xfee4ad70,
    receiver=0xa8144b0, e=0xfee4a8a0) at kernel/qapplication.cpp:2635
    #13 0x00909dff in QApplication::notify (this=0xfee4ad70, receiver=0xa8144b0,
    e=0xfee4a8a0) at kernel/qapplication.cpp:2421
    #14 0x00892f05 in QApplication::sendSpontaneousEvent (receiver=0xa8144b0,
    event=0xfee4a8a0) at qapplication.h:494
    #15 0x0088b3d8 in QETWidget::translateMouseEvent (this=0xa8144b0, event=0xfee4ac30)
    at kernel/qapplication_x11.cpp:4288
    #16 0x00888cd3 in QApplication::x11ProcessEvent (this=0xfee4ad70, event=0xfee4ac30)
    at kernel/qapplication_x11.cpp:3439
    ---Type <return> to continue, or q <return> to quit---
    #17 0x008a5e84 in QEventLoop:rocessEvents (this=0xa5d6ce0, flags=4)
    at kernel/qeventloop_x11.cpp:192
    #18 0x0091f234 in QEventLoop::enterLoop (this=0xa5d6ce0)
    at kernel/qeventloop.cpp:198
    #19 0x0091f150 in QEventLoop::exec (this=0xa5d6ce0) at kernel/qeventloop.cpp:145
    #20 0x0090a8a7 in QApplication::exec (this=0xfee4ad70)
    at kernel/qapplication.cpp:2758
    #21 0x0808ae0a in main (argc=1, argv=0xfee4aee4) at BCommon/main.cpp:148

    and

    (gdb) r
    Starting program: /cygdrive/c/_devroot/SCE/pootle/branches/RDdev_PSSGTool/BarleyMow/PSSGToolDllD.exe

    Program received signal SIGSEGV, Segmentation fault.
    0x39f8e02d in qt-mt333!?collidesWith@QCanvasRectangle@@UBE_NPBVQCanvasItem@@@Z
    () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    (gdb) bt
    #0 0x39f8e02d in qt-mt333!?collidesWith@QCanvasRectangle@@UBE_NPBVQCan vasItem@@@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #1 0x39f8e442 in qt-mt333!?collisions@QCanvas@@QBE?AVQCanvasItemList@@ ABVQPointArray@@PBVQCanvasItem@@_N@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #2 0x39f8e1c3 in qt-mt333!?collisions@QCanvasItem@@QBE?AVQCanvasItemLi st@@_N@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #3 0x39f8e2aa in qt-mt333!?collisions@QCanvas@@QBE?AVQCanvasItemList@@ ABVQRect@@@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #4 0x39f8e226 in qt-mt333!?collisions@QCanvas@@QBE?AVQCanvasItemList@@ ABVQPoint@@@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #5 0x0091dabe in PSSGToolDllD!?GetClassStr@BExcepWkBuild_CreateWkCr iteriaFailure_c@@SA?AVRDstr@@XZ ()
    #6 0x0091dfc2 in PSSGToolDllD!?GetClassStr@BExcepWkBuild_CreateWkCr iteriaFailure_c@@SA?AVRDstr@@XZ ()
    #7 0x009235a2 in PSSGToolDllD!?GetClassStr@BExcepWkBuild_CreateWkCr iteriaFailure_c@@SA?AVRDstr@@XZ ()
    #8 0x39df0a55 in qt-mt333!?event@QWidget@@MAE_NPAVQEvent@@@Z ()
    from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #9 0x39d509c8 in qt-mt333!?internalNotify@QApplication@@AAE_NPAVQObjec t@@PAVQEvent@@@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #10 0x39d5023a in qt-mt333!?notify@QApplication@@UAE_NPAVQObject@@PAVQE vent@@@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #11 0x39d0e4eb in qt-mt333!?sendSpontaneousEvent@QApplication@@CA_NPAVQ Object@@PAVQEvent@@@Z () from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #12 0x39d0889e in qt-mt333!?winMouseButtonUp@QApplication@@SAXXZ ()
    from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #13 0x39d05e2e in qt-mt333!?winFocus@QApplication@@QAEXPAVQWidget@@_N@Z ()
    from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #14 0x77d48734 in USER32!GetDC () from /cygdrive/c/WINDOWS/system32/user32.dll
    #15 0x00060a5a in ?? ()
    #16 0x00000201 in ?? ()
    #17 0x00000001 in ?? ()
    #18 0x01900069 in ?? ()
    #19 0x39d05880 in qt-mt333!?winFocus@QApplication@@QAEXPAVQWidget@@_N@Z ()
    from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #20 0x77d48816 in USER32!GetDC () from /cygdrive/c/WINDOWS/system32/user32.dll
    #21 0x39d05880 in qt-mt333!?winFocus@QApplication@@QAEXPAVQWidget@@_N@Z ()
    from /cygdrive/c/Qt/3.3.3/bin/qt-mt333.dll
    #22 0x77d489cd in USER32!GetWindowLongW ()
    from /cygdrive/c/WINDOWS/system32/user32.dll
    #23 0x00000000 in ?? () from
    (gdb) quit

    Both of these traces show 2 of the 3 possible crash sites. I do not know which it will be till iit happens. The collisions trace above would be called from BGraphCanvas::GetDlgHitHoverOver() function.

    Cya Illya

Similar Threads

  1. Replies: 4
    Last Post: 19th February 2009, 11:10
  2. How to constantly refresh time on a view
    By salmanmanekia in forum Qt Programming
    Replies: 5
    Last Post: 23rd June 2008, 12:44
  3. QDateTime GMT add sec. or - sec. from locale time....
    By patrik08 in forum Qt Programming
    Replies: 2
    Last Post: 20th February 2007, 16:39
  4. c++, placement delete upon exception
    By stinos in forum General Programming
    Replies: 6
    Last Post: 31st October 2006, 15:38
  5. Problem with pointers while using localtime() and time()
    By jamadagni in forum General Programming
    Replies: 7
    Last Post: 11th January 2006, 15:48

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.