[PyQt] how to optimize custom widgets drawing? it was faster with qt-4.2 then qt-4.3 and 4.4...

Marcell Mars marcell.mars at gmail.com
Wed Nov 12 23:36:41 GMT 2008


i did custom widget as alternative user interface for sooperlooper
[0].. you can see the widget in action here:
http://www.viddler.com/explore/marcell/videos/6/

then i composed a lot of them onto QWidget and you could see them in
action here:
http://www.viddler.com/explore/marcell/videos/7/
(there is a tag at 1:50 so you don't need to listen to introduction to
the project)

as you could see because of rounded shape of the widget i used quite a
lot drawPie.. this is one of the examples of drawing implementation:

  def paint(self, painter, option, widget):
    if not self.nextstate:
      painter.setBrush(self.background)
      painter.setPen(self.pen)
      painter.drawEllipse(self.rectangle)

      painter.setBrush(self.color)
      painter.drawPie(self.rectangle, 90*16, -self.cyclepos *16)
    else:
      painter.setBrush(self.background)
      painter.setPen(self.pen)
      painter.drawEllipse(self.rectangle)

      painter.setBrush(Qt.black)
      painter.setPen(self.pen)
      painter.drawPie(self.rectangle, 90*16, -self.cyclepos *16)

      self.brush.setColor(self.color)
      self.brush.setStyle(Qt.Dense3Pattern) # texture
      painter.setBrush(self.brush)
      painter.setPen(self.pen)
      painter.drawPie(self.rectangle, 90*16, -self.cyclepos *16)

i redraw the widget as i get information over OpenSoundControl
protocol... the one of the implementation goes like this:

def updateLoopPos(loopnumber, looppos):
  if mySooperLooperWidget.myCycleTime[loopnumber].cyclelen != 0:
    mySooperLooperWidget.myCycleTime[loopnumber].cyclepos = (looppos -
(int(looppos/mySooperLooperWidget.myCycleTime[loopnumber].cyclelen) *
mySooperLooperWidget.myCycleTime[loopnumber].cyclelen))/mySooperLooperWidget.myCycleTime[loopnumber].cyclelen*360
    mySooperLooperWidget.myLoopCycles[loopnumber].currentloop =
int(looppos/mySooperLooperWidget.myCycleTime[loopnumber].cyclelen)
   mySooperLooperWidget.myCycleTime[loopnumber].update()
   mySooperLooperWidget.myLoopCycles[loopnumber].update()

and this QWidget.update() at the end of updateLoopPos worked quite
fine in qt-4.2 (not sure about 4.3) and PyQt4 from that time... it
didn't use more than 40% of cpu together with X process... (around 20%
for my python process and usually X process would increase for 20%
while qt app is visible)...

everything was driving quite smooth... regardless of cpu usage :o)

after upgradeing to 4.3 everything slowed down drastically... i didn't
really checked that much... just got back to older version...

with 4.4 it didn't slowed down but increased cpu to 100% and system
(gentoo linux 2.6.2*-rt) became unusable...

found out that it was because of .update() method for every update
from sooperlooper.. that's the info every 20ms...

so i got rid of the .update().. but i needed some loop to update the
redrawing coz it didn't do that on it's own...

did QTimer to trigger update every 100ms or every second... it
works... the system is not completely stolen from qt app but still cpu
goes up to 100% (even after every second)...

i don't know what to do to solve this problem... i can use this app
with older versions of qt/PyQt but there are people who are interested
in checking the app.. can't tell them to go with some very specific
version...

hope that i wouldn't need to go and rewrite widgets in c++ and then
getting back them through PyQt4 bindings...

part of the application is ipython terminal from where one could
change everything in real time in the application... that's basically
why python is so important here (aside i don't really know c++ :))

thanx

p.s. the (messy) code could be found in git here:
http://git.savannah.gnu.org/gitweb/?p=topot.git

[0] http://essej.net/sooperlooper/


More information about the PyQt mailing list