By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,758 Members | 1,250 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,758 IT Pros & Developers. It's quick & easy.

PyQt - clear widget for redraw

P: n/a

I want to draw some lines on a widget.
This works ok, but when I want to redraw, the old lines are still there.

How do I clear or refresh the widget, so I can draw a new set of lines?

Code snip below.

TIA

Peter
-------------------------
def paintLines(self, e):
p = QPainter(e)
mar = e.width()/100 # margin
vsp = 2 # vertical spacing
hrz = (e.width() - 2*mar)/100 # horizontal scalar
for i in range(100):
p.drawLine(mar,mar+vsp*i,hrz*(l1[i]+1),mar+vsp*i)
-------------------------

Jul 18 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Peter wrote:

I want to draw some lines on a widget.
This works ok, but when I want to redraw, the old lines are still there.

How do I clear or refresh the widget, so I can draw a new set of lines?


Call erase on your widget. Or redraw a rectangle yourself.
--
Regards,

Diez B. Roggisch
Jul 18 '05 #2

P: n/a
Diez B. Roggisch wrote:

Call erase on your widget. Or redraw a rectangle yourself.


Thanks, that works fine.
I just started using pyqt yesterday, and having trouble finding a reference
- most Qt stuff is written for c++.

Peter

Jul 18 '05 #3

P: n/a
Jim
Peter wrote:
Diez B. Roggisch wrote:

Call erase on your widget. Or redraw a rectangle yourself.


Thanks, that works fine.
I just started using pyqt yesterday, and having trouble finding a
reference - most Qt stuff is written for c++.

Peter


Boudewijn Rempt's book _GUI Programming with Python: QT Edition_
might be helpful. It's available online at:

http://www.opendocspublishing.com/pyqt/

You can also post your questions at:
PyKDE mailing list Py***@mats.imk.fraunhofer.de

sign up for the list at:
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde

There's also a PyQt wiki at:
http://www.diotavelli.net/PyQtWiki
(it's fairly new and a little light on content, but there's already some
good stuff there).
Jim

Jul 18 '05 #4

P: n/a
Peter wrote:
Thanks, that works fine.
I just started using pyqt yesterday, and having trouble finding a
reference - most Qt stuff is written for c++.


The neat thing on pyqt is that usually you can directly translate c++
examples to python. So there is no need to have a separate documentation
and other resources. The erase I looked up in the qt standard
documentation.

--
Regards,

Diez B. Roggisch
Jul 18 '05 #5

P: n/a
Diez B. Roggisch wrote:
Peter wrote:
Thanks, that works fine.
I just started using pyqt yesterday, and having trouble finding a
reference - most Qt stuff is written for c++.

The neat thing on pyqt is that usually you can directly translate c++
examples to python. So there is no need to have a separate documentation
and other resources. The erase I looked up in the qt standard
documentation.


Thanks
(and thanks to Jim for his response, too)

What I'm drawing is a series of lines (like a horizontal bar chart) and it
is updated several times a second. The problem is that it goes too fast.
I tried the time.sleep() function, but then it doesn't draw properly. It
seems to draw only part of the chart each time, and flickers.

Is there some way to make the display smoother?

TIA

Peter

Jul 18 '05 #6

P: n/a
> What I'm drawing is a series of lines (like a horizontal bar chart) and it
is updated several times a second. The problem is that it goes too fast.
I tried the time.sleep() function, but then it doesn't draw properly. It
seems to draw only part of the chart each time, and flickers.


Usually there is no "to fast" in graphics - so I've got to admit I'm not
sure what you are talking about.

Where does the data to draw come from, and how fast is it actually coming? A
flickering sensation usually stems from the redrawing done so fast it
interfers with the vertical retrace.

Maybe it helps to put your sleep not in the drawing code, but between the
arrival of different data sets to draw, thus limiting the redraws to an
amount of lets say 10/s.

If you'd fill us in with some more details, the suggestions might be better.
And I think it would be worth asking these qustions on the PyKDE list Jim
has mentioned - I'm also there :)

--
Regards,

Diez B. Roggisch
Jul 18 '05 #7

P: n/a
Diez B. Roggisch wrote:
Maybe it helps to put your sleep not in the drawing code, but between the
arrival of different data sets to draw, thus limiting the redraws to an
amount of lets say 10/s.
Yes - tried that, but gives incomplete draw / flicker.
If you'd fill us in with some more details, the suggestions might be
better. And I think it would be worth asking these qustions on the PyKDE
list Jim has mentioned - I'm also there :)


More details:
the idea is to provide a graphics demo of sort algorithms for my 13 year old
son. A number of lines of differring lengths are shown on the screen, and
you can watch as these are sorted, step by step. So you can see the
difference between bubble sort, ripple sort, etc.
Code copied below.
Improving the smoothness of the display is the main thing I'm after.
Also, how can I write the counters to the form? It uses the LCD widget now,
but there must be another way.

TIA

Peter

-- sort1.py ---
#!/usr/bin/python
#
# demo of sort algorithms, using PyQt

import sys, random, time
from qt import *

from frmtest import frmTest

class dlgForm(frmTest):

def __init__(self, parent=None):
frmTest.__init__(self, parent)
self.connect(self.cmdQuit, SIGNAL("clicked()"),self,
SLOT("close()"))
self.connect(self.cmd2, SIGNAL("clicked()"), self.reshuffle)
self.connect(self.cmdSort, SIGNAL("clicked()"), self.sort1)
self.connect(self.cmdBubble, SIGNAL("clicked()"), self.bubble)
self.connect(self.cmdRipple, SIGNAL("clicked()"), self.ripple)
self.connect(self.cmdShell, SIGNAL("clicked()"), self.shells)
self.refresh()

def reshuffle(self):
global cComp, cSwap, b1, b2, r1, r2
cComp, cSwap, b1, b2 = [0,0,0,len(l1)]
random.shuffle(l1)
self.refresh()

def sort1(self):
global cComp, cSwap, b1, b2, r1, r2
cComp, cSwap, b1, b2 = [0,0,0,len(l1)]
l1.sort()
self.refresh()

def bubble(self): # simple bubble sort
global cComp, cSwap, b1, b2, r1, r2
cComp, cSwap, b1, b2 = [0,0,0,len(l1)]
b1 = 0
b2 = len(l1)
for i in range(len(l1)):
b2 = len(l1) - i
for j in range(b2-1):
cComp = cComp + 1
r1 = j
r2 = j+1
if l1[r1] > l1[r2]:
cSwap = cSwap + 1
l1[r1], l1[r2] = [l1[r2], l1[r1]]
self.refresh()
time.sleep(0.02)

def ripple(self):
global cComp, cSwap, b1, b2, r1, r2
cComp, cSwap, b1, b2 = [0,0,0,len(l1)]
bDone =1
while bDone:
bDone = 0
for j in range(b1,b2-1):
cComp = cComp + 1
r1 = j
r2 = j + 1
if l1[r1] > l1[r2]:
cSwap = cSwap + 1
bDone = 1
l1[r1], l1[r2] = [l1[r2], l1[r1]]
self.refresh()
time.sleep(0.01)
b2 = b2 - 1
for j in range(b2,b1,-1):
cComp = cComp + 1
r1 = j - 1
r2 = j
if l1[r1] > l1[r2]:
cSwap = cSwap + 1
bDone = 1
l1[r1], l1[r2] = [l1[r2], l1[r1]]
self.refresh()
time.sleep(0.01)
b1 = b1 + 1
self.refresh()

def shells(self):
global cComp, cSwap, b1, b2, r1, r2
cComp, cSwap, b1, b2 = [0,0, 0, len(l1)]
bDone = 1
span = 64
while bDone:
bDone = 0
for i in range(b1,b2-span):
r1 = i
r2 = i + span
cComp = cComp + 1
if l1[r1] > l1[r2]:
cSwap = cSwap + 1
bDone = 1
l1[r1], l1[r2] = [l1[r2], l1[r1]]
self.refresh()
time.sleep(0.01)

if not bDone: # if no changes that sweep, exit
break
bDone = 0
if span > 1:
span = int(span/2)

for i in range(b2-1,b1+span,-1):
r1 = i - span
r2 = i
cComp = cComp + 1
if l1[r1] > l1[r2]:
cSwap = cSwap + 1
bDone = 1
l1[r1], l1[r2] = [l1[r2], l1[r1]]
self.refresh()
time.sleep(0.01)
if span > 1:
span = int(span/2)
self.refresh()

def refresh(self):
self.LCDcount.display('%3d' % cComp) # update counters
self.LCDswap.display('%3d' % cSwap)
self.frame4.erase() # clear any old lines
p = QPainter(self.frame4)
mar = self.frame4.width()/100 # margin
vsp = 2 # vertical spacing
hrz = (self.frame4.width()-2*mar)/100 # horizontal scalar
p.setPen(QColor("black"))
for i in range(100):
p.drawLine(mar,mar+vsp*i,hrz*(l1[i]+1),mar+vsp*i)
p.setPen(QColor("blue"))
p.drawLine(mar,mar+vsp*b1-1,hrz*100,mar+vsp*b1-1)
p.drawLine(mar,mar+vsp*b2-1,hrz*100,mar+vsp*b2-1)
p.setPen(QColor("red"))
p.drawLine(mar,mar+vsp*r1+1,hrz*100,mar+vsp*r1+1)
p.drawLine(mar,mar+vsp*r2+1,hrz*100,mar+vsp*r2+1)

if __name__ == '__main__':
l1 = range(100) # numbers 0 to 99
b1 = 0 # blue line 1
b2 = 100 # blue line 2
r1 = 1 # red line 1
r2 = 1 # red line 2
cComp = 0 # count of compares
cSwap = 0 # count of swaps
app = QApplication(sys.argv)
QObject.connect(app, SIGNAL('lastWindowClosed()'),
app, SLOT('quit()'))
win = dlgForm()
app.setMainWidget(win)
win.show()
app.exec_loop()
-------------------------------------------------------
-------- frmtest.py --------------------------
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'frmtest.ui'
#
# Created: Sun Aug 1 15:55:11 2004
# by: The PyQt User Interface Compiler (pyuic) 3.8
#
# WARNING! All changes made in this file will be lost!

from qt import *

class frmTest(QMainWindow):
def __init__(self,parent = None,name = None,fl = 0):
QMainWindow.__init__(self,parent,name,fl)
self.statusBar()

if not name:
self.setName("frmTest")

self.setCentralWidget(QWidget(self,"qt_central_wid get"))

self.frame4 = QFrame(self.centralWidget(),"frame4")
self.frame4.setGeometry(QRect(40,109,441,210))
self.frame4.setMinimumSize(QSize(440,210))
self.frame4.setFrameShape(QFrame.StyledPanel)
self.frame4.setFrameShadow(QFrame.Raised)
self.frame4.setMargin(1)

self.cmd2 = QPushButton(self.centralWidget(),"cmd2")
self.cmd2.setGeometry(QRect(210,330,100,50))

self.cmdSort = QPushButton(self.centralWidget(),"cmdSort")
self.cmdSort.setGeometry(QRect(350,330,100,50))

self.cmdQuit = QPushButton(self.centralWidget(),"cmdQuit")
self.cmdQuit.setGeometry(QRect(70,330,100,50))

self.txtHello = QLabel(self.centralWidget(),"txtHello")
self.txtHello.setGeometry(QRect(50,20,450,76))
txtHello_font = QFont(self.txtHello.font())
txtHello_font.setPointSize(48)
self.txtHello.setFont(txtHello_font)
self.txtHello.setAlignment(QLabel.AlignCenter)

self.cmdBubble = QPushButton(self.centralWidget(),"cmdBubble")
self.cmdBubble.setGeometry(QRect(500,109,80,40))

self.cmdRipple = QPushButton(self.centralWidget(),"cmdRipple")
self.cmdRipple.setGeometry(QRect(500,160,80,40))

self.cmdShell = QPushButton(self.centralWidget(),"cmdShell")
self.cmdShell.setGeometry(QRect(500,210,80,40))

self.txtCopyright = QLabel(self.centralWidget(),"txtCopyright")
self.txtCopyright.setGeometry(QRect(40,380,400,21) )

self.LCDswap = QLCDNumber(self.centralWidget(),"LCDswap")
self.LCDswap.setGeometry(QRect(490,370,91,31))
self.LCDswap.setSegmentStyle(QLCDNumber.Flat)

self.LCDcount = QLCDNumber(self.centralWidget(),"LCDcount")
self.LCDcount.setGeometry(QRect(490,329,91,31))
self.LCDcount.setMode(QLCDNumber.Dec)
self.LCDcount.setSegmentStyle(QLCDNumber.Flat)

self.languageChange()

self.resize(QSize(603,438).expandedTo(self.minimum SizeHint()))
self.clearWState(Qt.WState_Polished)

def languageChange(self):
self.setCaption(self.__tr("test form"))
self.cmd2.setText(self.__tr("Reshuffle"))
self.cmdSort.setText(self.__tr("Sort"))
self.cmdQuit.setText(self.__tr("Quit"))
self.txtHello.setText(self.__tr("Sort Demo"))
self.cmdBubble.setText(self.__tr("Bubble"))
self.cmdRipple.setText(self.__tr("Ripple"))
self.cmdShell.setText(self.__tr("Shell"))
self.txtCopyright.setText(self.__tr("Copyright 2004 GPL Peter"))

def __tr(self,s,c = None):
return qApp.translate("frmTest",s,c)
---------------------------------------------------------

Jul 18 '05 #8

P: n/a
On Tuesday 03 August 2004 8:19 pm, Peter wrote:
Diez B. Roggisch wrote:
Maybe it helps to put your sleep not in the drawing code, but between the
arrival of different data sets to draw, thus limiting the redraws to an
amount of lets say 10/s.


Yes - tried that, but gives incomplete draw / flicker.


There are lots of standard graphics techniques for eliminating flicker when
drawing that you can exploit with PyQt. Double buffering for example - draw
to a QPixmap and then blit it to the QWidget.

Phil
Jul 18 '05 #9

P: n/a
Peter wrote:
Yes - tried that, but gives incomplete draw / flicker.

More details:
the idea is to provide a graphics demo of sort algorithms for my 13 year old
son. A number of lines of differring lengths are shown on the screen, and
you can watch as these are sorted, step by step. So you can see the
difference between bubble sort, ripple sort, etc.
Code copied below.
Improving the smoothness of the display is the main thing I'm after.

def refresh(self):
self.LCDcount.display('%3d' % cComp) # update counters
self.LCDswap.display('%3d' % cSwap)
self.frame4.erase() # clear any old lines
p = QPainter(self.frame4)
mar = self.frame4.width()/100 # margin
vsp = 2 # vertical spacing
hrz = (self.frame4.width()-2*mar)/100 # horizontal scalar
p.setPen(QColor("black"))
for i in range(100):
p.drawLine(mar,mar+vsp*i,hrz*(l1[i]+1),mar+vsp*i)
p.setPen(QColor("blue"))
p.drawLine(mar,mar+vsp*b1-1,hrz*100,mar+vsp*b1-1)
p.drawLine(mar,mar+vsp*b2-1,hrz*100,mar+vsp*b2-1)
p.setPen(QColor("red"))
p.drawLine(mar,mar+vsp*r1+1,hrz*100,mar+vsp*r1+1)
p.drawLine(mar,mar+vsp*r2+1,hrz*100,mar+vsp*r2+1)


To me it would seem the problems lies in the refresh routine,
you're erasing and then redrawing, a viewed object, this will
cause it to flicker around, even worse if using sizers.
There's probally a better way to do this, but when I've
been faced with this type of problem here's what I would try
and maybe it will help you or give you a different way to
look at it.

I'd create a clone of frame4, maybe frame5, only viewing
one at a time.

In my refresh routine I'd create some type of loop
and alternate them using .hide() .show() and only
do my drawing/erasing on the hidden object.

I think anyway you do it, you should only draw/erase
on a hidden object, you could also have frame4 and 5
be the same, but in the routine that calls refresh, .hide()
4, .show() 5, refresh then redraws 4, and on returning from
refresh, .hide() 5, .show()4. Anyway I thing you get the idea.

Just something I'd try.

Jul 18 '05 #10

P: n/a
Phil Thompson wrote:
There are lots of standard graphics techniques for eliminating flicker
when drawing that you can exploit with PyQt. Double buffering for example
- draw to a QPixmap and then blit it to the QWidget.


ok - I don't know what QPixmap or blit are, but it gives me some clues to
use in google. :)

Thanks for your help

Peter

Jul 18 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.