2012-06-12 7 views
6

Mit Qt4.8 auf einem Mint Linux 12, implementierte ich ein einfaches Fenster mit einem QTableView, um den Inhalt eines Modells anzuzeigen. Die Modelldaten werden kontinuierlich aktualisiert (Protokollnachrichten) und das Signal dataChanged() wird regelmäßig ausgegeben (d. H. Alle 100 ms).QWidget Update-Ereignisse, aber keine visuelle Aktualisierung

Das Problem, das ich sehe, ist stotternde visuelle Updates auf dem Tisch.

Ich habe einen Ereignisfilter im Fenster installiert, der updateRequest - Typ Ereignisse zählt, die ein Widget Repaint (auch auf Kind Widgets, d. H. Die tableView) auslösen sollte. Diese kommen mit einer durchschnittlichen Zeit von ~ 170ms dazwischen und einer Standardabweichung von ~ 90ms (was ziemlich groß ist, denke ich). Allerdings ist die wahrgenommene visuelle Update-Rate nur zwei oder drei Mal pro Sekunde und ich frage mich warum. Es scheint, dass nicht alle updateRequest Ereignisse ein Widget-Repaint auslösen oder dass das Fenstersystem visuelle Updates verschluckt.

Als ein zweiter Test, zwang ich das Fenster, sich selbst zu aktualisieren, indem alle 100ms repaint oder update aufrufen. Unter Verwendung von repaint sah ich eine entsprechende Zunahme der Ereignisse vom Typ updateRequest und eine Abnahme der Standardabweichung der Lücken; mit update stieg die Anzahl nicht. In beiden Fällen gab es jedoch nur einen moderaten Anstieg der wahrgenommenen Aktualisierungsrate.

Auch: Gibt es eine gute Methode um zu messen, wie oft ein Widget wirklich neu gestrichen wird, ohne seinen paintEvent Handler überladen zu müssen? Vielleicht etwas von QTest?


Update: ich meine Ereignisfilter erweitert auch Ereignisse paintEvent -Typ zu fangen. Es gibt nur eine einstellige Anzahl von Ereignissen im Vergleich zu> 1000 updateRequest -Typ-Ereignissen.

Antwort

1

Sie sollten die Signale aboutToBlock() und awake() des Ereignisverteilers instrumentieren und die Zeit zwischen ihnen mit einer QElapsedTimer messen. Die Instanz des Ereignisverteilers für den aktuellen Thread wird von der statischen QAbstractEventDispatcher::instance() zurückgegeben.

Wenn die Ereignisschleife für einen sehr kleinen Bruchteil Ihres Zeitmessungsfensters schläft, bedeutet dies, dass im GUI-Thread zu viel los ist. Sie können zählen, wie lange die Ereignisschleife zum Beispiel während der letzten Sekunde geschlafen hat. Wenn es unter 10% ist, können Sie langsame Updates und was nicht erwarten. Denken Sie daran, dass Update-Ereignisse mit Qt::LowEventPriority in die Warteschlange gestellt werden. Sie werden von standardmäßigen Warteschlangensignalen und fast allen anderen Ereignissen ausgeschlossen.

+0

Gute Idee! Ich habe derzeit einen engen Zeitplan für das Projekt, daher wird es ein paar Tage dauern, um das zu testen. Ich denke, das sollte mir einen guten Überblick über die Last geben, aber ich habe tatsächlich die updateRequest-Ereignisse gezählt, die mein Widget erreichen, und diese kommen viel näher (im Durchschnitt, Verstand) als die wahrgenommene Aktualisierungsrate. – arne

+0

Das Zählen ist in Ordnung, aber es sagt nichts über das zugrunde liegende Problem aus.Es sagt nur, es gibt ein Problem, und nun, Sie können es offensichtlich bemerken, ohne eine einzige Zeile Code zu schreiben :) –

0

QApplication::compressEvent verwirft QEvent::UpdateRequest, wenn es bereits einen unbearbeiteten gibt. Somit können sogar Repaint (s) sofort ohne Malen zurückkehren, wenn das Ereignis verworfen wird. Sie können überprüfen, ob Ihre updateRequest Ereignisse verworfen werden, indem Sie compressEvent überschreiben.

+0

Ich weiß über die Komprimierung, aber ist dies nicht in der Main Event-Schleife/QApplication irgendwo getan? Ich dachte, wenn ein updateRequest ein Widget erreicht, sollte dies bereits geschehen sein. – arne

+0

Sie haben Recht, die Komprimierung erfolgt im EventLoop. Ich habe missverstanden, wo du die Ereignisse zählst. Und wenn das Ereignis das Widget erreicht, ist die Komprimierung bereits abgeschlossen. Also, ignoriere meine Antwort. – Stefan