Seite 1 von 1

Resize eines QVBoxLayouts

Verfasst: 28. Mai 2009 14:14
von olebole
Hallo,

ich habe ein Fenster (bzw. ein DockWidget), das aus einem Hauptwidget und einem dazugehörigen horizintalen QScrollBar besteht. die beiden sind per QVBoxLayout in das Fenster eingebunden.

Das Hauptwidget besteht aus einem (matplotlib)-Diagramm und benötigt zum Neuzeichnen immer einige Millisekunden.

Wenn ich jetzt die Fenstergröße ändere, erscheint der Scrollbalken nicht immer korrekt: er wird entweder an der falschen Stelle gezeichnet (bei Änderung der Fensterhöhe), oder hat die falsche Größe (bei Änderung der Fensterbreite). Teilweise liegt er komplett außerhalb des Fensters und ist damit unbedienbar.

Ich habe mal die resizeEvent()- bzw. moveEvent()-Funktionen des Hauptwidgets und der Scrollbar überschrieben, um zu sehen, was da passiert. Offensichtlich kommen die Events in der falschen Reihenfolge:
(hier für eine Änderung der Fensterbreite):

Code: Alles auswählen

figure resize to QSize(803, 474) <-- erstes Event
figure resize to QSize(879, 474) <-- zweites Event
scroll resize to QSize(879, 15)  <-- zweites Event (falsch!!)
scroll resize to QSize(803, 15)  <-- erstes Event
Ich interpretiere das so:
  • das Hauptwidget erhält das erste Event und zeichnet sich selbst neu (*). Das dauert einige Zeit.
  • in dieser Zeit kommt das zweite Resize-Event.
  • weil das Widget bereits in einem Zeichen-Prozess ist, wird der zweite Request ignoriert (oder in eine Warteschlange gesetzt) und wird unmittelbar beendet.
  • das führt zur Verarbeitung des zweiten Events in der Scrollbar
  • nachdem das erste Neuzeichnen beendet ist, beginnt die Verarbeitung des ersten Events in der Scrollbar.
Wer macht hier was falsch?
  • Qt, weil es die Events nicht in der korrekten Reihenfolge liefert?
  • FigureCanvas (bzw. matplotlib), weil es die Verarbeitung des zweiten Events beendet, während das erste noch verarbeitet wird?
  • oder ich, weil ich irgendwas nicht verstanden habe?
Und, noch wichtiger: wie kann ich das vermeiden?

Viele Grüße

olebole

Verfasst: 29. Mai 2009 08:15
von archer
Erzeugst due das Hauptfenster und die Scrollbar zur Laufzeit (per Quellcode)?
Hast du evtl. den Parent nicht richtig vergeben?

Verfasst: 29. Mai 2009 09:08
von upsala
Event. wäre der Quellcode hierzu nicht schlecht...

Verfasst: 29. Mai 2009 09:26
von olebole
upsala hat geschrieben:Event. wäre der Quellcode hierzu nicht schlecht...
Kein Problem. Er ist zwar in Python, sollte aber trotzdem verständlich sein.
Falls nicht, kann ich gerne erklären.

Code: Alles auswählen

import random
import sys

from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure,SubplotParams

class DiagramWidget(QtGui.QWidget):
    def __init__(self, parent):
        QtGui.QWidget.__init__(self, parent)
        layout = QtGui.QVBoxLayout(self)
        self.setLayout(layout)
        self.diagram = InnerDiagramWidget(self)
        self.scrollbar = QtGui.QScrollBar(QtCore.Qt.Horizontal, self)
        layout.addWidget(self.diagram)
        layout.addWidget(self.scrollbar)
    
class InnerDiagramWidget(FigureCanvas):
    def __init__(self, parent):
        fig = Figure()
        self.axes = fig.add_subplot(111)
        range = xrange(10000)
        l = [ random.randint(-5, 5) for i in range ]
        self.axes.plot(range, l, drawstyle='steps')
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self,
                                   QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

a = QtGui.QApplication(sys.argv)
w = QtGui.QMainWindow()
w.setCentralWidget(DiagramWidget(w))
w.show()
a.exec_()