[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