Seite 1 von 1

QThreading eines großen QGraphicsView

Verfasst: 14. Oktober 2009 16:26
von olebole
Hallo Forum,

ich habe ein ziemlich großes QGraphicsView (bis zu ca. 100.000 Items), welches ich asynchron updaten möchte. Ereignisse, bei denen das Update auftreten soll, sind z.B. Mouse-Events u.ä. (Cursor verschieben).

Also gibt es bei mir einen eigenen QThread, der u.a. folgendes macht:

Code: Alles auswählen

for item in my_items:
    item.setBrush(QtGui.Brush(QtGui.QColor(...)))

scene.update()
Das crasht immer mal im setBrush() mit verschiedenen Meldungen (Segfault, double free, ...).
Ich vermute, dass das daran liegt, dass man die Objekte immer nur in ihrem "eigenen" Thread behandeln darf.

Also zu Beginn noch ein "scene.moveToThread(...)" eingebaut.
Das hilft aber nicht. Die einzelnen Items (QGraphicsRectItem) sind jedoch nicht von QObject abgeleitet (warum eigentlich nicht?), sodass ich dort moveToThread() nicht aufrufen kann.

Wie kann ich nun ein asynchrones Update der Map hinbekommen? Ich möchte es nicht im Haupt-Gui-Thread machen, da dann für die Zeit des Updates (einige Sekunden) die Oberfläche blockiert ist, was gerade bei der Verschiebung eines Mauscursors (welches das Update hervorruft) sehr störend wirken würde.

Viele Grüße

olebole

Verfasst: 14. Oktober 2009 17:23
von RHBaum
Wie kann ich nun ein asynchrones Update der Map hinbekommen? Ich möchte es nicht im Haupt-Gui-Thread machen
bist du auch bereit, schlechte Nachrichten zu verkraften ???

willst / musst du multithreaded 2D oder 3D zeichnen, musst du eine multihreading faehige biblo nehmen, bzw die low level schnittstellen (OpenGL / DirectX / DirectDraw) direkt befeuern.

die QT kann es nicht .... Die ganze interne objectverwaltung und das eventsystem sind nicht Threadsicher. Deshalb auch die Beschrankung, das alles was auf die GUI schiesst, in einem Thread zu laufen hat ...
Das ist die Schlechte Nachricht ! die gute: QGraphicsScene und QGraphicsItems sind keine GUI objecte.
ich habe ein ziemlich großes QGraphicsView (bis zu ca. 100.000 Items)
wenn du die Szene fertig gebaut hat ... wie lange braucht er um die komplett zu zeichen ???

Was verbraucht mehr Porzessorlast, die Anderung in deiner Szene ? oder das Erstellen, modifizieren ... verwerfen der QGraphicsItems in deiner QGraphicsScene ???

Deine QGraphicsScene darfst du sehrwohl in nem anderen Thread bearbeiten ... nur das anzeigen, also das Triggern des updates, muss ueber den GUI Thread erfolgen !

Wie stoesst du das aendern der Anzeige an ??? laesst du den kompletten view updaten, nur den momentan sichtbaren ausschnitt oder errechnest du bei jeder aenderung den ausschnitt der sich aendern wuerde, checkst ob der grad sichtbar ist, nimmst die Schnittmenge zwischen dem und den grad sichtbaren, und laeesst die neuziechnen ???
Also gibt es bei mir einen eigenen QThread, der u.a. folgendes macht:

Code:
for item in my_items:
item.setBrush(QtGui.Brush(QtGui.QColor(...)))

scene.update()

Das crasht immer mal im setBrush() mit verschiedenen Meldungen (Segfault, double free, ...).
sicher das der um setBrush crasht, und ned im update ?
ist die Szene an sich geschuetzt durch nen Mutex ???

Ciao ...

Verfasst: 14. Oktober 2009 17:38
von olebole
QGraphicsScene und QGraphicsItems sind keine GUI objecte.
Dann dürfte mein Code doch gar nicht crashen? Er tut es aber.
sicher das der um setBrush crasht, und ned im update ?
Soweit sicher als dass ich im Stacktrace meist etwas sehe wie

Code: Alles auswählen

*** glibc detected *** python: double free or corruption (out): 0x00007f73c000d2c0 ***
======= Backtrace: =========                                                                                
/lib/libc.so.6[0x7f73e26efcb8]
/lib/libc.so.6(cfree+0x76)[0x7f73e26f2276]
/usr/lib/libQtGui.so.4(_ZN6QBrushaSERKS_+0x32)[0x7f73e13d9d62]
/usr/lib/libQtGui.so.4(_ZN26QAbstractGraphicsShapeItem8setBrushERK6QBrush+0x15)[0x7f73e18bbdf5]
/usr/lib/python2.6/dist-packages/PyQt4/QtGui.so[0x7f73e211f449]
python(PyEval_EvalFrameEx+0x4e23)[0x4a2b03]
python(PyEval_EvalFrameEx+0x60ce)[0x4a3dae]
python(PyEval_EvalCodeEx+0x869)[0x4a4649]
python[0x5329ad]
python(PyObject_Call+0x5d)[0x41d3bd]
python[0x424f48]
python(PyObject_Call+0x5d)[0x41d3bd]
python(PyEval_CallObjectWithKeywords+0x56)[0x49cd46]
/usr/lib/python2.6/dist-packages/sip.so[0x7f73dd951715]
/usr/lib/python2.6/dist-packages/PyQt4/QtCore.so[0x7f73dd6176aa]
/usr/lib/python2.6/dist-packages/PyQt4/QtCore.so[0x7f73dd6332ac]
/usr/lib/libQtCore.so.4[0x7f73e0d31952]
/lib/libpthread.so.0[0x7f73e32953ba]
/lib/libc.so.6(clone+0x6d)[0x7f73e275dfcd]
======= Memory map: ========
Dort findet sich genau der Aufruf _ZN26QAbstractGraphicsShapeItem8setBrushERK6QBrush. Das heißt, dieser Aufruf bringt das System reproduzierbar zum Absturz. Wenn ich ihn durch etwas anderes ersetze -- zum Beispiel
item.brush().color().setRgb(...) -- funktioniert alles (bis zu qt 4.5.0, unter 4.5.2 wird das ignoriert, siehe meinen anderen Beitrag im Forum).