[PyQt] QProgressBar, repaint, and Mac OS X.

Jason Ferrara jason.ferrara at jacquette.com
Tue Jul 20 17:36:48 BST 2010


I have a need to update a QProgressBar while a slider is begin dragged, without processing user events.
. 
I tried calling QProgressBar.repaint(), as shown in the sample code below. This works fine for linux/X11 (and osx/X11), but for osx/aqua I never see the progress bar change. It seems that repaint() under osx has no effect. I'm guessing that it causes drawing to occur to the off screen buffer, but never copies that to the main screen.

I tried calling QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) instead of QProgressBar.update(). That makes the progress bar update correctly, but I end up with funny slider movements where it jiggles back and forth a bit instead of exactly tracking the mouse, and weird focus issues where the next few mouse clicks after the last call to QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) get sent to the wrong widget.

In case anyone is wondering why I need to do this...

My app does data visualization, and I have a slider that makes some adjustments to my display widget. Most of the time the adjustment occurs near instantaneously, so that the user sees the display update in real time as they drag the slider. But occasionally, depending on the nature of the data, the adjustment to the display widget can take up to 10 seconds. So when the adjustment takes a long time I need some way to inform the user that the app is processing their request (and hasn't hung) and give an estimate of how long its going to take for the screen to update. If I allow normal event handling while the adjustment to the widget is begin made (by calling processEvents() or running the adjustment in a separate thread) then the adjustment of the display widget would lag way behind the slider movement, and the user would have the ability to trigger some other operation on the display widget during the adjustment, which would lead to corruption of data in the widget.

Does anyone have any suggestions on how to get the same progress bar update behavior I see under X11 to occur under osx/aqua?

Thanks

- J

from PyQt4 import QtGui
from PyQt4.QtCore import Qt
import time
import sys

class TestWindow(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        l = QtGui.QVBoxLayout()
        slider = QtGui.QSlider(Qt.Horizontal, self)
        slider.setRange(0,100)
        l.addWidget(slider)
        self.pb = QtGui.QProgressBar(self)
        self.pb.setRange(0,20)
        l.addWidget(self.pb)
        self.setLayout(l)
        slider.valueChanged.connect(self.doStuff)

    def doStuff(self, v):
        for i in xrange(20):
            self.pb.setValue(i)
            self.pb.repaint()
            time.sleep(0.05)
        self.pb.reset()

app = QtGui.QApplication(sys.argv)
w = TestWindow()
w.show()
app.exec_()


Jason Ferrara
Jacquette Consulting, Inc.
710 Providence Road
Malvern, PA 19355
jason.ferrara at jacquette.com



More information about the PyQt mailing list