Qt: Recursive repaint detected
-
Mechanics schrieb:
Das processEvents hast du grad zum ersten mal erwähnt. Das kann grundsätzlich natürlich schon zu rekursiven Aufrufen führen.
Ich hab grad keine Lust, mich in dein konkretes Problem reinzudenken, aber grundsätzlich ist es so, dass ein Paint Event noch in der Event Queue ist, du rufst Process Events auf, und dasselbe Paint Event wird wieder abgearbeitet. Ich hab keine Ahnung, wie das bei Qt 5+ ist, aber bei Qt 4 ist es zumindest problematisch, wenn nicht ein harter Crash.Achso, naja, die Doku von Qt sagt jedenfalls, dass processEvents() thread-safe ist.
Ich werds mal raushauen und schauen, ob der Fehler nochmals auftritt. Wenn er nicht mehr auftritt, dann wars das und danke dir.
-
Nein, das wars nicht, habe eben einen Segfault bekommen.
Was für ein mieser Zufall.
-
Beim segfault müsstest du aber den Callstack sehen.
-
Der Debugger springt sofort in eine Asm-Datei, davon weiß ich leider nichts. Im Stack steht folgendes:
1 QPainter::drawPixmap(QPointF const&, QPixmap const&) 0x7ffff651218b 2 ?? 0x7ffff6b68b1b 3 ?? 0x7ffff6b5b766 4 QPushButton::paintEvent(QPaintEvent *) 0x7ffff6c1c0ee 5 QWidget::event(QEvent *) 0x7ffff6acf298 6 QApplicationPrivate::notify_helper(QObject *, QEvent *) 0x7ffff6a8a7bc 7 QApplication::notify(QObject *, QEvent *) 0x7ffff6a8f95f 8 QCoreApplication::notifyInternal2(QObject *, QEvent *) 0x7ffff5403280 9 QWidgetPrivate::sendPaintEvent(QRegion const&) 0x7ffff6ac81ba 10 QWidgetPrivate::drawWidget(QPaintDevice *, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *) 0x7ffff6ac8809 11 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *, QList<QObject *> const&, int, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *) 0x7ffff6ac94fc 12 QWidgetPrivate::drawWidget(QPaintDevice *, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *) 0x7ffff6ac8374 13 ?? 0x7ffff6a987bb 14 ?? 0x7ffff6a989a9 15 QWidgetPrivate::syncBackingStore() 0x7ffff6ab6f6f 16 QWidget::event(QEvent *) 0x7ffff6acf368 17 QApplicationPrivate::notify_helper(QObject *, QEvent *) 0x7ffff6a8a7bc 18 QApplication::notify(QObject *, QEvent *) 0x7ffff6a8f95f 19 QCoreApplication::notifyInternal2(QObject *, QEvent *) 0x7ffff5403280 20 QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *) 0x7ffff54051fc ... <More>
processEvents() hab ich übrigens rausgehauen.
-
Ich seh da soweit nichts großartig verdächtiges. Ist es der Hauptthread, was machen die anderen Threads grad? Kannst du an den Variablen usw. erkennen, was schiefgeht?
-
Mechanics schrieb:
Ich seh da soweit nichts großartig verdächtiges. Ist es der Hauptthread, was machen die anderen Threads grad? Kannst du an den Variablen usw. erkennen, was schiefgeht?
Das "Locals and Expressions"-Fenster ist leer, wenn der Debugger in die ASM-Zeile springt. Ich glaube es liegt am Mainthread, da ich wirklich keine QObject-Methoden vom Thread aus aufrufe. Wann kann ein Recursive Paint denn sonst noch auftreten? Echt nur wenn man in einem anderen Thread Objekte malt? Das ist bei mir nämlich nicht der Fall, in den Threads benutze ich ausschließlich nur Signals.
Hier nochmal der Callstack:
1 QTransform::type() const 0x7ffff6563080 2 QRasterPaintEngine::drawImage(QPointF const&, QImage const&) 0x7ffff64f4f15 3 QRasterPaintEngine::drawPixmap(QPointF const&, QPixmap const&) 0x7ffff64f9e4e 4 QPainter::drawPixmap(QPointF const&, QPixmap const&) 0x7ffff651214b 5 ?? 0x7ffff6b66cb5 6 ?? 0x7ffff6b5a8d5 7 QCommonStyle::drawControl(QStyle::ControlElement, QStyleOption const *, QPainter *, QWidget const *) const 0x7ffff6b05551 8 ?? 0x7ffff6b5b2e5 9 QProgressBar::paintEvent(QPaintEvent *) 0x7ffff6c1b1b0 10 QWidget::event(QEvent *) 0x7ffff6acf298 11 QProgressBar::event(QEvent *) 0x7ffff6c1bcee 12 QApplicationPrivate::notify_helper(QObject *, QEvent *) 0x7ffff6a8a7bc 13 QApplication::notify(QObject *, QEvent *) 0x7ffff6a8f95f 14 QCoreApplication::notifyInternal2(QObject *, QEvent *) 0x7ffff5403280 15 QWidgetPrivate::sendPaintEvent(QRegion const&) 0x7ffff6ac81ba 16 QWidgetPrivate::drawWidget(QPaintDevice *, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *) 0x7ffff6ac8809 17 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *, QList<QObject *> const&, int, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *) 0x7ffff6ac94fc 18 QWidgetPrivate::drawWidget(QPaintDevice *, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *) 0x7ffff6ac8374 19 ?? 0x7ffff6a987bb 20 ?? 0x7ffff6a989a9 ... <More>
-
Ich habe mal testhalber Qt::BlockedQueuedConnection ausprobiert und der Fehler scheint bisher nicht mehr aufzutreten. Ich melde mich dann mal wieder, falls der Fehler wieder auftaucht.
-
Qtnase schrieb:
Wann kann ein Recursive Paint denn sonst noch auftreten? Echt nur wenn man in einem anderen Thread Objekte malt?
Nein, hatte ich ja schon geschrieben. Ich kenn mich mit Qt5 übrigens nicht explizit aus, aber es würde mich schon stark überraschen, wenn man aus mehreren Threads malen könnte. Klar, du kannst in einem Seitenthread einen QPainter erstellen und in ein QImage malen (aber nicht QPixmap in Qt4), aber aus mehreren Threads in denselben QPainter zeichnen macht keinen Sinn.
BlockedQueuedConnection... Das ist jetzt nicht wirklich dafür gedacht, könnte aber schon Sinn machen, dass es hier damit funktioniert. Ich hätt aber eigentlich schon erwartet, einen "sauberen" Callstack zu sehen, bei dem ersichtlich ist, dass der Aufruf tatsächlich rekursiv ist. Wenn man das Problem nicht genau versteht, kann es sein, das man das jetzt kurzfristig löst, später aber noch mehr Probleme bekommt.
-
Das mit dem recursive paint event geht auch, indem man selbst paintEvent() überschreibt und dort indirekt einen neuen QPainter aufmacht, z.B. indem man einen QDialog öffnet (vorzüglich demonstriert das Jürgen Wolf in seinem Qt4-Programmieren-Buch - nicht nachmachen ;)).
Implementierst du denn irgendwo paintEvent selber?
-
Cremant schrieb:
Implementierst du denn irgendwo paintEvent selber?
Nope.
Also seitdem ich die Verbindungen mit Qt::BlockingQueuedConnection gemacht habe, trat der Fehler nicht mehr auf.