[pygtk] R: Re: How drawing, Drawable, ....work in pygtk !

euro_ii at libero.it euro_ii at libero.it
Mon Dec 21 14:46:46 WST 2009



go on http://sourceforge.net/projects/pythoncad/ we strongly use it :-)




>----Messaggio originale----
>Da: esr at thyrsus.com
>Data: 21/12/2009 5.05
>A: 
"chuong nguyen vien"<chuong_nguyenvien at yahoo.com>
>Cc: <pygtk at daa.com.au>
>Ogg: 
Re: [pygtk] How drawing, Drawable, ....work in pygtk !
>
>chuong nguyen vien 
<chuong_nguyenvien at yahoo.com>:
>> Hello,
>> 
>> I have just played with pygtk a 
couple of day and everything seems ok but the drawing system. I dont know how 
it works basically and got confused, very confused !
>> 
>> I read somewhere on 
the internet it say that i have to follow a pattern to make it work, and the 
key to that pattern is : we need to implement the drawing code within the 
expose event handler. Why ? 
>> 
>> I tried to make some drawing code outside 
the expose event handler, and didnt write a expose event handler at all. It 
didnt work. It just appear a window without anything, or my drawing stuff didnt 
display.
>> 
>> So basically, how the expose event and drawing in GTK work or 
relate to each other ?
>> 
>> Thanks 
>> 
>> Chuong
>
>Here's the canvas-
management class I wrote for the GPSD test client. You
>may be able to use it 
as a model.  Note how (a) all the actual drawing 
>is done in the expose event, 
(b) redrawing is implemented with the
>queue_draw() method, (c) the canvas's 
actual size allocation 
>is picked up for later use in the on_size_allocate 
event.
>
>class SkyView(gtk.DrawingArea):
>    "Satellite skyview, encapsulates 
pygtk's draw-on-expose behavior."
>    # See <http://faq.pygtk.org/index.py?
req=show&file=faq18.008.htp>
>    HORIZON_PAD = 20	# How much whitespace to 
leave around horizon
>    SAT_RADIUS = 5	# Diameter of satellite circle
>    
GPS_PRNMAX = 32	# above this number are SBAS satellites
>    def __init__
(self):
>        gtk.DrawingArea.__init__(self)
>        self.set_size_request
(400, 400)
>        self.gc = None  # initialized in realize-event handler

>        self.width  = 0 # updated in size-allocate handler
>        self.
height = 0 # updated in size-allocate handler
>        self.connect('size-
allocate', self.on_size_allocate)
>        self.connect('expose-event',  self.
on_expose_event)
>        self.connect('realize',       self.on_realize)

>        self.pangolayout = self.create_pango_layout("")
>        self.
satellites = []
>
>    def on_realize(self, widget):
>        self.gc = widget.
window.new_gc()
>        self.gc.set_line_attributes(1, gtk.gdk.LINE_SOLID,

>                                    gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_ROUND)
>

>    def on_size_allocate(self, widget, allocation):
>        self.width = 
allocation.width
>        self.height = allocation.height
>        self.
diameter = min(self.width, self.height) - SkyView.HORIZON_PAD
>
>    def 
set_color(self, spec):
>        "Set foreground color for drawing."
>        
self.gc.set_rgb_fg_color(gtk.gdk.color_parse(spec))
>
>    def draw_circle
(self, widget, x, y, diam, filled=False):
>        "Draw a circle centered on 
the specified midpoint."
>        widget.window.draw_arc(self.gc, filled,

>                               x - diam / 2, y - diam / 2,

>                               diam, diam, 0, 360 * 64)
>
>    def draw_square
(self, widget, x, y, diam, filled=False):
>        "Draw a square centered on 
the specified midpoint."
>        widget.window.draw_rectangle(self.gc, filled,

>                                     x - diam / 2, y - diam / 2,

>                                     diam, diam)
>
>    def draw_string(self, 
widget, x, y, letter):
>        "Draw a letter on the skyview."
>        self.
pangolayout.set_text(letter)
>        # FIXME: When the layout object can 
report its size, use it
>        self.window.draw_layout(self.gc, x-5, y-10, 
self.pangolayout)
>
>    def pol2cart(self, az, el):
>        "Polar to 
Cartesian coordinates within the horizon circle."
>	az *= (math.pi/180)	# 
Degrees to radians
>        # Exact spherical projection would be like this:
>	
# el = sin((90.0 - el) * DEG_2_RAD);
>	el = ((90.0 - el) / 90.0);
>	xout = int
((self.width / 2) + math.sin(az) * el * (self.diameter / 2))
>	yout = int((self.
height / 2) - math.cos(az) * el * (self.diameter / 2))
>        return (xout, 
yout)
>
>    def on_expose_event(self, widget, event):
>        self.set_color
("white")
>        widget.window.draw_rectangle(self.gc, True, 0,0, self.width,
self.height)
>        # The zenith marker
>        self.set_color("gray")

>        self.draw_circle(widget, self.width / 2, self.height / 2, 6)
>        
# The circle corresponding to 45 degrees elevation.
>        # There are two 
ways we could plot this.  Projecting the sphere
>        # on the display 
plane, the circle would have a diameter of
>        # sin(45) ~ 0.7.  But the 
naive linear mapping, just splitting
>        # the horizon diameter in half, 
seems to work better visually.
>        self.draw_circle(widget, self.width / 
2, self.height / 2,
>                         int(self.diameter * 0.5))

>        self.set_color("black")
>        # The horizon circle
>        self.
draw_circle(widget, self.width / 2, self.height / 2,
>                         
self.diameter)
>        # The compass-point letters
>        (x, y) = self.
pol2cart(0, 0)
>        self.draw_string(widget, x, y+10, "N")
>        (x, y) 
= self.pol2cart(90, 0)
>        self.draw_string(widget, x-10, y, "E")
>        
(x, y) = self.pol2cart(180, 0)
>        self.draw_string(widget, x, y-10, "S")

>        (x, y) = self.pol2cart(270, 0)
>        self.draw_string(widget, x+10, 
y, "W")
>        # The satellites
>        for sat in self.satellites:

>            (x, y) = self.pol2cart(sat.azimuth, sat.elevation)
>            if 
sat.ss < 10:
>                self.set_color("Black")
>            elif sat.ss 
< 30:
>                self.set_color("Red")
>            elif sat.ss < 35:

>                self.set_color("Yellow");
>            elif sat.ss < 40:

>                self.set_color("Green3");
>            else:
>                
self.set_color("Green1");
>            if sat.PRN > SkyView.GPS_PRNMAX:

>                self.draw_square(widget,
>                                 x-
SkyView.SAT_RADIUS, y-SkyView.SAT_RADIUS,
>                                 2 * 
SkyView.SAT_RADIUS + 1, sat.used);
>            else:
>                self.
draw_circle(widget,
>                                 x-SkyView.SAT_RADIUS, y-
SkyView.SAT_RADIUS,
>                                 2 * SkyView.SAT_RADIUS + 
1, sat.used);
>            self.set_color("Black")
>            self.draw_string
(widget, x, y+10, str(sat.PRN))
>    def redraw(self, satellites):
>        
"Redraw the skyview."
>        self.satellites = satellites
>        self.
queue_draw()
>
>
>-- 
>		<a href="http://www.catb.org/~esr/">Eric S. 
Raymond</a>
>_______________________________________________
>pygtk mailing 
list   pygtk at daa.com.au
>http://www.daa.com.au/mailman/listinfo/pygtk
>Read the 
PyGTK FAQ: http://faq.pygtk.org/
>




More information about the pygtk mailing list