PDA

View Full Version : When is the best time to delete a QCanvasItem



irudkin
10th February 2006, 15:24
Hi

Using Qt3.3.3.

This may seem a bizzare question but hear me out. I have a derived QCanvas class which has derived QCanvasItems (QCanvasRectangleItems) in/on it. The canvas items are parented to this derived QCanvas.

I use the delete on an instance of a QCanvasItem to remove it from the canvas. Inside the destructor of the derived QCanvasItem I call hide().

However peridically when I have delete a derived QCanvasItem, a tiny bit later a fatal crash has occurred in either QCanvasItemList::drawUnique( QPainter& painter ) try in access a duff QCanvasItem pointer, or QCanvas::collisions when itereating through its list of items, or in QCanvas::update().

So should I be doing anything else to ensure a QCanvasItem is removed from the QCanvas internal list(s)?

Thanks
Cya Illya

wysota
10th February 2006, 17:10
No, deleting the item is enough to remove it from all QCanvas data structures. If you experience a crash, it must be because of your own datastructures, probably some invalid pointer or something. Can we see some code you expect to be erroneus?

irudkin
13th February 2006, 12:25
Hi

I have managed to make the crash more regular now. The scenerio is as follows:
I delete a group of items. I then need to detect when my mouse is over another item by calling collisions(); Collisions tried to iterate through a list of visible items from its chunks.
It is crashing when it tries to reference an item from this list.

I also get a situation where being fast with the mouse I move a groups of widgets over the area of the canvas which previous had items there but just been deleted. Again iterating items from Qt chunks.

It will also crash in QCanvas::update() when using QCanvasItem::drawUnique() again when a little earlier in the call stack retrived a list of items from chunks() to reference. This may either be from my code or when the QCanvasView performs an update straight from Qt code (none of my functions are called in the call stack)

It seems the QCanvas chunks and/or the chunks held by each item is out of date.

I have to be sure its not my remaining items iterated through allItems() and tested each item is valid just prior to an update() or collision() on the theory if I had access to a bad item so would QCanvas. My const QCanvasItemList lista = allItems() of items are all fine.

In summary I delete some widgets. Then Qt may on a call to collision() or update() which iterates a list of items retrieved from chunks crash accessing an item pointer. Lines 13 and 14.


QCanvasItemList QCanvas::collisions(const QPointArray& chunklist,
const QCanvasItem* item, bool exact) const
{
QPtrDict<void> seen;
QCanvasItemList result;
for (int i=0; i<(int)chunklist.count(); i++) {
int x = chunklist[i].x();
int y = chunklist[i].y();
if ( validChunk(x,y) ) {
const QCanvasItemList* l = chunk(x,y).listPtr();
for (QCanvasItemList::ConstIterator it=l->begin(); it!=l->end(); ++it) {
QCanvasItem *g=*it;
if ( g != item ) {
if ( !seen.find(g) ) {
seen.replace(g,(void*)1);
if ( !exact || item->collidesWith(g) )
result.append(g);
}
}
}
}
}
return result;
}

wysota
13th February 2006, 14:11
Do you use multiple threads in your application? Could we see some of your code?

irudkin
13th February 2006, 15:33
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.



BGraphWgtBase_c::~BGraphWgtBase_c( void )
{
hide();
DeleteChildren();
}

//virtual
bool BGraphWgtBase_c::Redraw()
{
QRect rectToRefresh( boundingRect() );
m_pParent->setChanged( rectToRefresh );
m_pParent->SetDoARedrawPlease();

return RDstatus::success;
}

bool BGraphWgtBase_c::SetMarkForDelete()
{
m_bIsMarkedForDelete = true;
hide();

// Now go through all this widget's child widgets and mark for delete too
ListWgts::iterator it = m_listChildWidgets.begin();
while( it != m_listChildWidgets.end() )
{
BGraphWgtBase_c * pWgt = *it;
if( pWgt == NULL )
{
continue;
}
pWgt->hide();
pWgt->SetMarkForDelete();

// Move to next
++it;
}

return RDstatus::success;
}
// Slot
// Visited every 500ms to do canvas updates
void BGraphCanvas_c::SlotUpdateTimer()
{
if( m_bDoARedrawPlease )
{
m_bDoARedrawPlease = false;

try
{
update();
}
catch( ... )
{

}
}

return;
}

// Set by BGraphWgtBase_c to flag that at least one item on the canvas
// would like to be updated
bool BGraphCanvas_c::SetDoARedrawPlease()
{
m_bDoARedrawPlease = true;
return RDstatus::success;
}

// This function goes through all the widgets ( canvas items ) registered with this canvas
// and deletes the items which have been marked for deletion. Widgets for this canvas class
// operation do not get deleted at source when not needed as they may be still in use, or their
// children still in use. They could be contained in the canvas's various containers at the
// time they are deemed as not needed anymore. This function and the
// BGraphWgtBase_c::SetMarkForDelete function enacts a delayed delete system. At the
// source hide the widget and mark for delete. This function is called sometime later and will delete the
// marked items. BGraphWgtBase_c::SetMarkForDelete function also at the same time informs the BGraphWgtMgr_c
// of the widget's removal so it can update its records.
// Note: Very important when this is called. For example do not call at end of
// mouseReleaseEvent(). QCanvas does behind the scenes work
// on all it canvas items after mouseReleaseEvent() and so deleting any before then
// is not a good and causes a crash.
bool BGraphCanvas_c::DeleteMarkedWgts()
{
BGraphWgtBase_c * pCurrentSelectedWgt = GetView()->GetCurrentSelectedItem();
bool bDeleteWgt = false;
QCanvasItemList listAllItems = allItems();
QCanvasItemList::iterator it = listAllItems.begin();
while( it != listAllItems.end() )
{
BGraphWgtBase_c * pWgt = dynamic_cast< BGraphWgtBase_c * >( *it );
if( (pWgt != NULL) && pWgt->IsMarkForDelete() )
{
if( pWgt == pCurrentSelectedWgt )
{
GetView()->SetCurrentSelectedItem( NULL );
}

delete pWgt;
bDeleteWgt = true;
}

// Next
++it;
}

if( bDeleteWgt )
{
update();
}

return RDstatus::success;
}

QCanvasItemList BGraphCanvas_c::GetDlgsHitHoverOver( const QPoint & vMousePos )
{
QCanvasItemList wgtHoverOverHitList;
QPoint realMousePos( GetRealX( vMousePos.x() ), GetRealY( vMousePos.y() ) );
wgtHoverOverHitList = Collisions( realMousePos );

return wgtHoverOverHitList;
}

//virtual
void BGraphCanvas_c::update()
{
// The try catch is here to stop QCanvas crash if it comes
// across an invalid pointer to a QCanvasItem. This is a bug which
// has been difficult to solve as when is the right time to delete
// a QCanvasItem. See DeleteWgts() in this class which is there to
// try to stop this sort of thing happening.
try
{
QCanvas::update();
}
catch( ... )
{
;
}
}

QCanvasItemList BGraphCanvas_c::Collisions( const QPoint & vMousePos )
{
try
{
return collisions( vMousePos );
}
catch( ... )
{
;
}

QCanvasItemList list;
return list;
}

// vpWgtExceptThisOne would normally be the current selected widget
const RDstr BGraphCanvas_c::GetDlgHitHoverOver( const QPoint & vMousePos, BGraphWgtBase_c * vpWgtExceptThisOne )
{
RDstr dlgId;

if( !IsOnCanvas( vMousePos ) )
{
return dlgId;
}

QPoint realMousePos( GetRealX( vMousePos.x() ), GetRealY( vMousePos.y() ) );
QCanvasItemList listDlgHitByMouse = Collisions( realMousePos );

// User clicked on a widget that recognised itself as hitable/selectable
dlgId = pDlgItem->GetId();

return dlgId;
}

// return: valid id or no id = no hit
const RDstr BGraphCanvas_c::GetDlgHit( const QPoint & vMousePos, BGraphWgtBase_c * vpWgtExceptThisOne )
{
return GetDlgHitHoverOver( vMousePos, vpWgtExceptThisOne );
}



bool BGraphCanvas_c::IsThisWidgetHit( const QPoint & vPosMouse, const RDstr & vWidgetId )
{
bool bHaveHitSpecificWidget = false;

QCanvasItemList listHitItems = GetDlgsHitHoverOver( vPosMouse );

return bHaveHitSpecificWidget;
}

void BGraphCanvasView_c::mousePressEvent( QMouseEvent * vpEvent )
{
// Clean out widgets marked for deletion. Very important this is called here
// and not say on mouseReleaseEvent(). QCanvas does behind the scenes work
// on all it canvas items after mouseReleaseEvent() and so deleting any before then
// is not a good and causes a crash.
m_pGraphAreaCanvas->DeleteMarkedWgts();

// Has user clicked on an canvas area dialog (QCanvasItem )
m_mouseButtonPressCursorPos = viewportToContents( vpEvent->pos() );

m_currentSelectedAreaDlgId = m_pGraphAreaCanvas->GetDlgHit( m_mouseButtonPressCursorPos, NULL );
m_pCurrentSelectedWgt = m_pGraphAreaCanvas->GetDlgObj( m_currentSelectedAreaDlgId );
if( NULL == m_pCurrentSelectedWgt )
{
// Reset all widget depths accept the current selected widget
m_pAGraph->GetGraphCanvasWgtMgr()->WgtsSetAllToNominalAreaZDepth( NULL );
return;
}

// Create store for event into to be passed onto all hit widgets (canvas items)
BGraphWgtEventInfo_s sEventInfo;

// Pass event onto selected widget (canvas item)
if( m_pCurrentSelectedWgt->MousePressEvent( sEventInfo ) )
{
// Inform the client using BPkgGraph that possible item valid for selection is selected
m_pAGraph->SetCurrentlySelectedWidgetId( m_pCurrentSelectedWgt->GetId() );
}

// Pass event onto rest of hit widgets. These are not the most forward Z pos
// widgets.
m_pGraphAreaCanvas->MousePressEvent( sEventInfo );

// Reset all widget depths accept the current selected widget
m_pAGraph->GetGraphCanvasWgtMgr()->WgtsSetAllToNominalAreaZDepth( m_pCurrentSelectedWgt );
}

void BGraphCanvasView_c::mouseReleaseEvent( QMouseEvent * vpEvent )
{
// Create store for event into to be passed onto all hit widgets (canvas items)

if( NULL != m_pCurrentSelectedWgt )
{
// Pass event onto selected widget (canvas item)
m_pCurrentSelectedWgt->MouseReleaseEvent( sEventInfo );
}

// Pass event onto rest of hit widgets. These are not the most forward Z pos
// widgets.
m_pGraphAreaCanvas->MouseReleaseEvent( sEventInfo );

// Reset all widget depths accept the last selected widget
m_pAGraph->GetGraphCanvasWgtMgr()->WgtsSetAllToNominalAreaZDepth( m_pCurrentSelectedWgt );
}


void BGraphCanvasView_c::contentsMouseMoveEvent( QMouseEvent * vpEvent )
{
// Create store for event into to be passed onto all hit widgets (canvas items)

// User clicked on an canvas area dialog (QCanvasItem )
if( m_bMouseLeftButtonHitAreaDlg && m_bMouseLeftButtonDown )
{
// to use this m_currentSelectedAreaDlgId
if( NULL != m_pCurrentSelectedWgt )
{
// Pass event onto selected widget (canvas item)
m_pCurrentSelectedWgt->MouseContentMoveEvent( sEventInfo );
}
}

// Pass event onto rest of hit widgets. These are not the most forward Z pos
// widgets.
m_pGraphAreaCanvas->MouseContentMoveEvent( sEventInfo );

// User just moving the mouse over the canvas. Highlight most forward hit widget if any.
// Unhighlight previous widget if it still exists
// Turn off all/any highlighted hit widget areas
QPoint mousePos( vpEvent->pos() );
const RDstr wgtId = m_pGraphAreaCanvas->GetDlgHitHoverOver( mousePos, pWgtExceptThisOne );

// Crash in collisions in GetDlgHitHoverOver()
// snip
}
}

// Update the view
m_pGraphAreaCanvas->update();
}

wysota
13th February 2006, 16:09
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?

yop
13th February 2006, 18:56
Or post a debugger backtrace to lead us somewhere...
Anyway I'd also delete the item like:


delete pWgt;
pWgt = NULL;

I have the feeling that the qt "internals" would check for null pointers before using them (I know I do) ;)

irudkin
14th February 2006, 10:50
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::processEvents (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_NPBVQCan vasItem@@@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

irudkin
15th February 2006, 12:15
Hi

I have just created a example project that reproduces the the crashes I get. It is a VC++ project in the .zip file.
Unzip and build the project. It builds against Qt3.3.3.

Run the example. Click in the QCanvasView whitespace to bring up a context menu to add some QCanvasItems (set of 4 at a time) to the canvas. Add a few. Then select a QCanvasItem to bring up a context menu item to delete it and the rest of the set. Move the other items around. Add a new item. Delete another. Move/select. Continue until there is a crash.

Let me know how you get on.

Cya Illya

wysota
15th February 2006, 12:29
I get lots or warnings and in the end, a linking error (undefined vtable for BGraphCanvasView_c). Maybe you should correct those before continuing? And a working .pro file would be nice, too, not everybody uses M$ VS.

irudkin
15th February 2006, 16:55
Hi
Please find .pro file content for the files in the .zip above.
This has been tested and compiles though with float to int warnings and runs.
Cya Illya

# ----------------------------------------------------------
# Project generated by QMsNet v1.0.0
# Template used: Basic Application
# Template version: 1.1
# ----------------------------------------------------------

TEMPLATE = app
TARGET = QCanvasCrashTest
LANGUAGE = C++
CONFIG += qt warn_on stl exceptions rtti


UI_DIR = ui
MOC_DIR = output
OBJECTS_DIR = output
DESTDIR = .

INCLUDES += .

SOURCES += main.cpp
SOURCES += BGraphCanvas.cpp
SOURCES += BGraphCanvasView.cpp
SOURCES += BGraphWgtBase.cpp
SOURCES += BGraphWgtDialog.cpp

HEADERS += BGraphCanvas.h
HEADERS += BGraphCanvasView.h
HEADERS += BGraphWgtBase.h
HEADERS += BGraphWgtDialog.h

irudkin
16th February 2006, 17:12
Hi

It has been fixed. Horray. A nice chap at Qt support saw the problem and luckily my example had made the problem worst. Anyway here it is:

// Note: if you reimplement the boundingRect() function
//of your QCanvasRectangle subclass and change the values this function
//returns while the item is visible, sure to call QCanvasPolygonalItem::invalidate().
// If you do not the QCanvas will use one bounding rectangle when adding the
// item to the chunks and a different one
//when removing, causing the internal list of items to still contain your
//item after it has been hidden. When the item is deleted, QCanvas still
//believes that the item is visible and uses the pointer and thus your
//program crashes. You will need to call
//invalidate() on the item if you do change it.

I did not realise from the Qt documentation overriding the boundRect() and changing the size would have this effect.

Cya Illya

ksbaydar
8th March 2007, 22:28
Hi

It has been fixed. Horray. A nice chap at Qt support saw the problem and luckily my example had made the problem worst. Anyway here it is:

// Note: if you reimplement the boundingRect() function
//of your QCanvasRectangle subclass and change the values this function
//returns while the item is visible, sure to call QCanvasPolygonalItem::invalidate().
// If you do not the QCanvas will use one bounding rectangle when adding the
// item to the chunks and a different one
//when removing, causing the internal list of items to still contain your
//item after it has been hidden. When the item is deleted, QCanvas still
//believes that the item is visible and uses the pointer and thus your
//program crashes. You will need to call
//invalidate() on the item if you do change it.

I did not realise from the Qt documentation overriding the boundRect() and changing the size would have this effect.

Cya Illya

I have seen the same problems about removing properly the QCanvasItem from the QCanvas. But I did not see the satisfying answer.

I have faced with the same problem. After two days, we found and solved the result as in the following.

When we try to delete the any items from the QCanvas by using the delete statement, we are facing the problem with resize or some thing like that which causes to call the update function of the QCanvas. In detail, it call the drawUnique() function. Anyway, althoug we delete the QCanvasItem from QCanvas, it stores another list which is a memeber of QCanvasChunk. That is, QCanvas uses another list in order to improve the its performance. It uses chunks which displays the changed items in the QCanvas. Therfore, we have to clear this list as well.

In order to do that, First, we can put setVisible(false) or hide() or invalidate() functions at the begining of the overloaded areaPoints() function. Then, we can add setVisible(true) or show() or update() functions at the end of the areaPoints() function.


setVisible() (or the others listed above) call to removeFromChunks() or addChunks() function. So any action which causes to call update function can not reason any conflists between the removed QCanvasItems and the internal list ( the list member of QCanvasChunk ) .

I think it should be a function of QCanvas which clear the chunks as well and it should be used in the destructor like hide as documented.

Best regards
Serhat