Qt: Fensterinhalt flackert bei Änderung des Layouts
-
Ich kämpfe gerade mit ein paar "Flacker-Problemen" eines Fensters, in dem sich ein Layout ändern kann.
Als einzige wirklich Abhilfe habe ich bisher QWidget::setFixedSize() gefunden (sämtliches Geflacker und Gewackel verschwindet), allerdings ist das entsprechende Widget Teil eines QSplitters, sodass ich nach dem Fixieren der Größe ein Problem habe.Mein nächster Ansatz ist nun, das entsprechende QWidget vor den resizeEvent()'s des eigenen Layouts "zu schützen" und nur noch die durch den QSplitter ausgelösten umzusetzen (sozusagen semi-fixedsize). Es scheint allerdings, als könne ich bei einem Event nicht erkennen, wodurch es ausgelöst wurde, was die Aufgabe etwas schwieriger gestaltet.
Weiß jemand, wie ich dieses Problem lösen könnte? Natürlich wäre ich auch an völlig anderen Vorschlägen interessiert, mein Flackern loszuwerden. Aber die Sache mit dem resizeEvent scheint mir gar kein schlechter Ansatz - wenn das denn machbar ist, wie ich mir das vorstelle.
-
Ich habe gerade den eventFilter entdeckt und mir gedacht, dass ich damit arbeiten könnte. Jedoch scheint das mit einem QLayout nicht zu funktionieren, der eventFilter wird einfach nicht aufgerufen (mit einem anderen getesteten Objekt geht es).
Weiß denn niemand Rat?
-
Ich hab bisher noch nie Flacker-Probleme mit Resizen eines Layouts gehabt. Selbst komplexere Sachen wie die Mail-Liste+darunter Ansicht einer HTML-Mail in Kmail mit zig Einträgen geht absolut smooth. Dank Double-Buffering sollte es "Flackern" sowieso nicht geben. Das höchste der Gefühle ist eine leichte Verzögerung, aber im Prinzip gar nicht tragisch.
Kannst du mal Code posten? Ich nehme stark an, du hast in dem Layout auch Widgets liegen in denen du selber zeichnest. Evtl. liegt das Problem in dessen Implementierung.
-
Ich habe ein Widget mit einem Layout darauf. In das Layout füge ich nun hin und wieder Widgets ein oder entferne welche. Da das Layout die ganze Zeit sichtbar ist, scheint es bei jedem Aufruf von take() oder addWidget() einige Aktionen durchzuführen, die zu einem resize() des Parent-Widgets führen.
Erst wenn alle neuen Widgets zugefügt sind, scheint das Layout zu merken, dass sämtliche Änderungen in der Größe überflüssig waren und ich erhalte das von mir gewünschte Ergebnis.Eigentlich ist keines der beteiligten Objekte ein Element einer eigenen Klasse und ich versuche auch nicht, darauf etwas zu zeichnen. Nur zum Testen habe ich mal ein eigenes Parent-Widget erstellt, um mir anzuschauen, ob da wirklich bei jedem Flackern ein resizeEvent() ausgelöst wird. Das war der Fall, deswegen wollte ich dort den Fuß in die Tür bekommen.
bool MyUnsizableWidget::eventFilter(QObject * obj , QEvent * event) { if(this->layout() != NULL && event->type() == QEvent::Resize) { if(obj == (QObject *)this->layout()) return(true); else return(QWidget::eventFilter(obj , event)); } else return(QWidget::eventFilter(obj , event)); }
Der Filter wird an ganz anderer Stelle auch installiert
(layout->installEventFilter(myUnsizableWidget);
Hier noch die Zeile, die Flackern hervorruft:
for(i = 0 ; i < ListeMitWidgets->count() ; i ++) myUnsizableWidget->layout->addWidget(ListeMitWidgets->at(i));
Mehr Code ist leider nicht drin, ich weiß nicht, wo das Problem liegt.
-
Ich habe noch immer keine vernünftige Lösung für mein Problem gefunden. Ich habe über ein eigenes Layout nachgedacht, aber ebenso wie an anderer Stelle reicht das einfach nicht aus, um das Flackern des Widgets an der Wurzel packen zu können.
Weiß nicht jemand, was man dagegen tun kann? Mir fällt einfach nichts mehr ein. Und mit dem Geflackere des Fensterinhalts ist mein Programm nicht wirklich zu gebrauchen.
PS: Der eventFilter-Versuch ist ins leere gelaufen, ebenso sämtliche Versuche, das Layout ein wenig auszutricksen.
-
Den schlimmsten Teil des Problemes konnte ich umgehen, indem ich die event()-Funktion des entsprechenden Widgets ein wenig verändert habe:
bool MyWid::event(QEvent * e) { if(e->type() != QEvent::LayoutRequest) return(QSplitter::event(e)); else return(true); }
Ist sicher keiner perfekte Lösung, scheint aber bisher keine ungewollten Nebeneffekte zu besitzen.
Falls noch jemand einen besseren Vorschlag hat, bin ich ganz Ohr :).
-
google: QSplitter Qt 4.6, 1st hit, click More, read:
QSplitter resizes its children dynamically by default. If you would rather have QSplitter resize the children only at the end of a resize operation, call setOpaqueResize(false)
Vielleicht hilft das weiter?
-
padreigh schrieb:
QSplitter resizes its children dynamically by default. If you would rather have QSplitter resize the children only at the end of a resize operation, call setOpaqueResize(false)
Vielleicht hilft das weiter?
Nein, das hat nichts mit meinem Problem zu tun. Das Attribut ist ohnehin so gesetzt, da das Fenster sonst zuviel arbeitet, wenn man an den SplitterHandles zieht (opaqueResize = "Splitter-Inhalt anzeigen beim Verschieben des Handles").
Der Splitter findet das "end of a resize operation" offensichtlich auch an Stellen, an denen er es besser nicht finden sollte - wenn z.B. sein Inhalt geändert wird, was völlig unabhängig sein kann vom Herumschieben der Handles.padreigh schrieb:
google: QSplitter Qt 4.6, 1st hit, click More, read:
Und was soll das? Nachdem ich mich eine Woche mit dem Problem herumgeschlagen und gefühlt die ersten 500 Google-Hits zu jedem auch nur peripher damit zusammenhängenden Thema gelesen habe, ist ein "frag google, noob" nicht die beste Reaktion.
Aber trotzdem danke für den Versuch, vielleicht habe ich ja wirklich irgendwo nur ein kleines Detail übersehen.
-
du könntest das Programm ja mal auf das Nötigste (den Fehler) runterkochen und den Code posten. Dann können wir testen, ob der Fehler bei uns auch auftritt. Aber wenn man ihn erstmal "isoliert" hat, dann findet er sich meist von allein
-
Stiefel2000 schrieb:
padreigh schrieb:
google: QSplitter Qt 4.6, 1st hit, click More, read:
Und was soll das? Nachdem ich mich eine Woche mit dem Problem herumgeschlagen und gefühlt die ersten 500 Google-Hits zu jedem auch nur peripher damit zusammenhängenden Thema gelesen habe, ist ein "frag google, noob" nicht die beste Reaktion.
Lediglich eine Beschreibung meines Vorgehens - noob stand da nirgends. Da du das aber schon kanntest, versuch (falls selbst noch nicht getan): Wenn du weisst das du 10 Elemente einfügen willst (weißt du das oder added der dynamisch irgendwann irgendwieviele irgendwasse?), frag das Widget nach seiner derzeitigen Größe, setz die minimum/maximum Größe temporär auf den Wert und die QSizePolicy auf fixed. Füge deine 10 Elemente ein und mach das mit der minumum/maximum Größe und QSizePolicy rückgängig. Dann "könnte" eventuell das Flackern durch einen Ruck ersetzt werden. Alternativ könntest du auch versuchen das Widget zu hide'n, alle Sachen zu adden und wieder zu show'n ... falls selbst noch nicht versucht - das wird dann aber zu 2 Rucks führen ... eins beim Widget hiden und eins beim shown. Du könntest auch den kompletten Splitter kurz durch ein QLabel der selben Größe ersetzen, die Sachen adden und zurücktauschen ... oder testen ob ein setEnabled(false) QSplitter sich anders verhält beim adden von Zeug? Das wäre das was ich zuerst testen würde. Das QLabel könntest du mit dem QPixmap des QSplitters vorm adden verzieren um ein Flackern dort zu verhindern, ... du könntest auch nur das pixmap vom Zielwidget in ein QLabel packen, Label reinhängen, widget raushängen, sachen einfügen, label wieder raus und widget wieder rein ...