Posts Tagged 'Clutter'
2011-07-02

For the last few days, I've been gathering resources for making a prototype of a shishi odoshi(a type of fountain) out of PVC tubing.

The story goes something like this: A few years back I sprouted a fig tree from a clipping of fig tree root, and when the new fig tree was about a foot tall, I gave it to my mother. Fast forward to the present and mom is complaining about deer eating the fig tree. She wants a "deer chaser" fountain to scare the deer away.

Mom: I need a fountain
Jezra: can't you just shoot the deer? mmm venison
Mom: NO! I just need a fountain to scare them away
Jezra: Fine, I'll see what I can do

Start with some cardboard

The silver bullet

A few tubes of rolled beer box gave me a basic idea of the sizes of tubing I would need for the prototype.

Cut some PVC

I started with a 4' x 1.5" PVC pipe that I measured once and cut into the pieces that I needed.

  • 18" spout brace
  • 11" opposing brace
  • 4" arm stop
  • 11" arm yea, I made up all of those name

Making the Arm

The arm was cut at the 4" mark and the remainder of the arm was covered with gorilla tape. A coupler was added to bind the two arm pieces back together. Combined with the tape, this configuration emulates the partitioning that is found in bamboo

Almost ready

Boring holes in PVC is a pain.

Brace stays were cut form .5" PVC. (that's a measurement of the inside diameter) Check out that sweet arm.... it looks just like bamboo!

It's alive!

A piece of .5" PVC was use as the spout on the spout brace. Some leftover tubing from the homebrew setup was connected to a little sump pump that moves about a gallon of water a minute.

This is the test in my kitchen.

Now I need to find some bamboo and make the real thing. In hind sight, I probably could have just made this thing out of bamboo from the get-go. Oh well, I suppose I paint it to look like bamboo.

OK, that's enough, go make stuff.

Comments
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
6 plus 9
Answer:
required
2009-12-25
Recently, I've been getting a lot of hits from people searching for "pyclutter examples". Unfortunately, the code that most people find is my hello world example that was written for Clutter 0.6 and since the API for Clutter has change quite a bit since I wrote that code, the code doesn't work with the latest stable release of Clutter.

I've considered updating the code to work with the more modern Clutter, but that wouldn't really be fun would it? Besides, someone has already updated the code. Thanks Ryan. Why don't I write another example? Don't mind if I do.

There is nothing new Clutter-wise in this example to differentiate it from the hello world example except that this code will run with the latest Clutter.


What we have here, is John Conway's Game of Life where each cell is a Clutter Rectangle.
#!/usr/bin/env python # copyright 2009 jezra lickter #this software is licensed under the GPLv3  http://www.gnu.org/licenses/gpl.txt import clutter import random class Game:     def __init__(self,cell_size):         self.cells = []         #create a clutter stage         self.stage clutter.Stage()         #set the stage size in x,y pixels         self.stage.set_size(500,500)         self.stage.set_title("The Game of Life")         self.stage_widthself.stage_height self.stage.get_size()         #define some clutter colors in rgbo (red,green,blue,opacity)         self.color_black =clutter.Color(0,0,0,255         self.color_green =clutter.Color(0,255,0,255)         self.color_blue =clutter.Color(0,0,255,255)         #set the clutter stages bg color to our black         self.stage.set_color(self.color_black)         #we will need to check on the key presses from the user         self.stage.connect('key-press-event'self.parseKeyPress)         self.stage.connect("destroy"self.quit)         '''fill the screen with rectangles'''         num_cols int(self.stage_width/cell_size)         num_rows int(self.stage_height/cell_size)         cells_to_create num_cols*num_rows         0         for row in range(num_rows):             0             self.cells.append( [] )             print "%i cells to create" % (cells_to_create)             for column in range(num_cols):                 #set the column index to a rect that is cell_size by cell_size                 self.cells[row].appendclutter.Rectangle() )                 self.cells[row][column].set_size(cell_size,cell_size)                 self.cells[row][column].set_position(x,y)                 #add this cell to the stage                 self.stage.add(self.cells[row][column])                 self.cells[row][column].set_color(self.color_green)                 self.cells[row][column].set_opacity(0)                 x+=cell_size             cells_to_create-=num_cols                          y+=cell_size         print "cells created"         #get some data about the rows         self.row_count  len(self.cells)         self.col_count len(self.cells[0])              self.cell_count self.row_count*self.col_count         #make a timer to do stuff for us         self.timeline clutter.Timeline(duration=500)         #when the timer finishes running, we want to determine the life         self.timeline.connect("completed",self.compute_life)         #increase linearly         alpha clutter.Alpha(self.timelineclutter.LINEAR)         #make some opacity behaviours that we will apply to the cells         self.dieBehaviour clutter.BehaviourOpacity(255,0,alpha)         self.aliveBehaviour clutter.BehaviourOpacity(0,255,alpha)              def parseKeyPress(self,actor,event):         if event.keyval == clutter.keysyms.q:             self.quit()         elif event.keyval == clutter.keysyms.c:             self.compute_life()         elif event.keyval == clutter.keysyms.r:             self.reseed()          def quit(self,widget=None):         clutter.main_quit()          def run(self):         self.stage.show_all()         self.seed_life()         self.compute_life()         clutter.main()              def reseed(self):         for in range(self.row_count):             for in range(self.col_count):                 if self.cells[r][c].get_opacity()>0:                     self.cells[r][c].set_opacity(0)         self.seed_life()              def seed_life(self):         print "adding random life"         #loop through the rows         for in range(self.row_count):         #loop through the columns             for in range(self.col_count):                 #generate a number                 random.randint(0,4)                 if i==0:                     # x,y is alive                     self.cells[r][c].set_opacity(255)              def compute_life(self,asset=None):         #detach all objects from the behaviors         self.dieBehaviour.remove_all()         self.aliveBehaviour.remove_all()         for in range(self.row_count):             for in range(self.col_count):                 if self.cells[r][c].get_opacity()>0:                     alive=True                 else:                     alive=False                 ln self.living_neighbors(r,c)                 if alive and ln<or ln>):                     #this cell will die; boohoo                     self.dieBehaviour.apply(self.cells[r][c] )                 elif not alive and ln==3:                     #this cell is now alive; damn zombies                     self.aliveBehaviour.apply(self.cells[r][c] )                                      #start the timeline again         self.timeline.start()                      def living_neighbors(self,r,c):         alive 0         r_min r-1         r_max r+1         c_min c-1         c_max c+1         if r==:             r_min=r         elif == self.row_count-1:             r_max=r         if c==:             c_min=c         elif == self.col_count-1:             c_max=c                      tr r_min         tc c_min         cells_computed=0         while not tr r_max:             tc c_min             while not tc c_max:                 if tr!=or tc!=):                     cells_computed+=1                     if self.cells[tr][tc].get_opacity()>0:                         alive+=1                 tc+=1             tr+=1         return alive          if __name__=="__main__":     game Game(5)     game.run()

When running the code: press "q" to quit, press "r" to reset.

One issue I have with this code is that when creating the rectangles for the cells, creation slows down significantly after creating about 3000 rectangles. The app runs fine when all of the cells are created, but the slow down during creation really irks me. Perhaps I need more RAM or I should write the code in Vala using SDL?

Now stop reading, and go play with colored rectangles.
Comments
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
6 minus 4
Answer:
required
2009-05-10
Quite a while ago, I began playing with the clutter library as a way to move and display graphics on a fullscreen application interface. With the 0.8 release of the clutter library, the fullscreen function didn't seem to work properly anymore and I was rather perturbed. Instead of taking up the entire screen, a "fullscreened" app would behave as though one had maximized a window. However, earlier today I revisited some python code that uses pyclutter to access the clutter library and I came up with a hack that will solve the fullscreen problem and actually redefines the problem in my eyes.
First, let me show some code that does not work as expected:
#!/usr/bin/env python import clutter class test:     def __init__(self):         #create a stage         self.stage clutter.Stage()         #set the stage to be fullscreen         self.stage.fullscreen()         #show the screen         self.stage.show_all()         #get the key presses         self.stage.connect('key-press-event'self.quit)         #start the clutter main loop         clutter.main()     def quit(self,object,event):         #quit the main loop         clutter.main_quit() if __name__=="__main__":     #make an instance of the test     test()

After trying different various possible fixes, it appeared that the bug is actually
"the stage fullscreen function behaves like maximize if used before the clutter main loop".
What does that mean? It means that the fullscreen function will work if the function is called after the clutter main() function. But how does one call a function after a mainloop has been initialized? I'm glad you asked.

Check out this code with the fix in place:
#!/usr/bin/env python import clutter import gobject class test:     def __init__(self):         #create a stage         self.stage clutter.Stage()         #show the screen         self.stage.show_all()         #get the key presses         self.stage.connect('key-press-event'self.quit)         #add a fullscreen function to the gobject timeout         gobject.timeout_add(10,self.go_fullscreen)         #start the clutter main loop         clutter.main()     def go_fullscreen(self):         self.stage.fullscreen()     def quit(self,object,event):         #quit the main loop         clutter.main_quit() if __name__=="__main__":     #make an instance of the test     test()

Since the clutter library uses Gobject objects as base classes for most clutter classes, including the mainloop, one can use gobject.timeout_add() to call a function after a set amount of time. In the fixed code, a function that calls fullscreen was set to run a few milliseconds after the clutter.main() was called.

Now I need to port the code to Vala and make sure the fix works with the Vala Clutter bindings as well.
Comments
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
8 minus 3
Answer:
required
2008-05-12
This is not a tutorial. This is an example of code and some ramblings of my experience writing the code. What does the code do? What we have here is a basic image viewer using pyclutter textures as the output of the image. The image viewer will run in fullscreen mode and will animate images on and off of the screen when the user pressed either the left or right arrow keys. Here we go.

#!/usr/bin/env python
import sys
import os, os.path
import clutter
import gtk

class imageList:
def __init__(self,dir):
# we need an array and a default index of the array
self.imagelist =[]
self.imagelist_index = 0
#go find the images in the directory
self.find_images(dir)

def get_index_image(self):
return self.imagelist[self.imagelist_index]

def get_left_image(self):
return self.imagelist[ self.get_next_left_index() ]

def get_right_image(self):
return self.imagelist[ self.get_next_right_index() ]

def get_index(self):
return self.imagelist_index

def get_next_left_index(self):
left = self.imagelist_index-1
if left<0:
left = self.get_image_count()-1
return left

def get_next_right_index(self):
right = self.imagelist_index+1
if right>=self.get_image_count():
right = 0
return right

def decrement_index(self):
self.imagelist_index = self.get_next_left_index()

def increment_index(self):
self.imagelist_index = self.get_next_right_index()

def get_image_count(self):
return len(self.imagelist)

def find_images(self,dir):
#loop through the files in the folder
print "searching "+dir+" for images...."
assets = os.listdir(dir)
for i in range(len(assets) ):
asset_path = os.path.join(dir,assets[i] )
if os.path.isdir(asset_path):
#if the asset is a directory, recurse
self.find_images(asset_path)
pass
else:
#how do we know if this is a usable image?
#try to get a pixbuf from the image
try:
"""TODO: assume the majority of files are images and delete
the bad files from the array when they are displayed to the
user, this should vastly improve start up time"""
pixbuf = gtk.gdk.pixbuf_new_from_file(asset_path)
#add this asset to the imagelist
print "Found: "+asset_path
self.imagelist.append(asset_path)
except:
#fail this isn't a usable image
pass

class imageViewer:
def __init__(self):
#is there a sys.argv?
if len(sys.argv)>1:
self.create_image_list(sys.argv[1])
else:
self.print_help("No image directory selected")
#if we made it this far, we can start making the clutter interface
self.stage = clutter.Stage()
#make the stage full screen
self.stage.fullscreen()
#hide the mousey
self.stage.hide_cursor()
#we need to record the stage size
#NOTE: I should try to use the CLUTTER_STAGE_WIDTH, but it may only be part of the c library
(self.stage_w,self.stage_h) = self.stage.get_size()
#define a clutter color in rgbo (red,green,blue,opacity)
color_black =clutter.Color(0,0,0,255)
#set the clutter stages bg color to our black
self.stage.set_color(color_black)
#we will need to check on the key presses from the user
self.stage.connect('key-press-event', self.parseKeyPress)
#make three textures: left,right,and center
self.l_image=clutter.Texture()
self.r_image=clutter.Texture()
self.c_image=clutter.Texture()
#add the textures to the stage
self.stage.add(self.l_image)
self.stage.add(self.r_image)
self.stage.add(self.c_image)
#hide all of the images
self.l_image.set_opacity(0)
self.c_image.set_opacity(0)
self.r_image.set_opacity(0)
#creae a timeline for the texture animations
self.texture_timeline = clutter.Timeline(fps=25,duration=1000)
#create an alpha to describe the movement for behaviours
self.texture_alpha = clutter.Alpha(self.texture_timeline, clutter.ramp_inc_func)
'''we will need a behaviour to handle animation between the left and center(lc),
and between the center and right(cr) '''
self.lc_behaviour = clutter.BehaviourPath(self.texture_alpha)
self.cr_behaviour = clutter.BehaviourPath(self.texture_alpha)
#show all stage items and enter the clutter main loop
self.stage.show_all()
self.set_center_image()
clutter.main()

#we will need to scale the textures to fill the screen
def scale_texture(self,texture):
#NOTE: texture.get_size is not working properly, use the size of the pixbuf
#(twidth,theight) = texture.get_size()
buf = texture.get_pixbuf()
twidth = buf.get_width()
theight = buf.get_height()
if twidth>theight:
scale = ((self.stage_w+0.0)/twidth)
else:
scale = ((self.stage_h+0.0)/theight)
#perform the scaling
print scale
texture.set_property("width",twidth*scale)
texture.set_property("height",theight*scale)

def set_center_image(self):
#hide the texture
self.c_image.set_opacity(0)
#center is the current index
buf = gtk.gdk.pixbuf_new_from_file( self.imagelist.get_index_image() )
self.c_image.set_pixbuf( buf )
#scale the images
self.scale_texture(self.c_image)
#center the center image
(tex_width,tex_height) = self.c_image.get_size()
xloc = self.stage_w/2 - tex_width/2
yloc = self.stage_h/2 - tex_height/2
self.c_image.set_position(xloc,yloc)
#make the center image visible
self.c_image.set_opacity(255)

def set_right_image(self):
#right is right image
buf=gtk.gdk.pixbuf_new_from_file( self.imagelist.get_right_image() )
self.r_image.set_pixbuf( buf )
#scale the image
self.scale_texture(self.r_image)
#move the right image off of the screen and center vertically
(tex_width,tex_height) = self.r_image.get_size()
yloc = self.stage_h/2 - tex_height/2
self.r_image.set_position(self.stage_w,yloc )
self.r_image.set_opacity(255)
def set_left_image(self):
#l_image is left image
buf = gtk.gdk.pixbuf_new_from_file( self.imagelist.get_left_image() )
self.l_image.set_pixbuf( buf )
#scale the texture
self.scale_texture(self.l_image)
#move the left image off of the screen and center vertically
(tex_width,tex_height) = self.l_image.get_size()
yloc = self.stage_h/2 - tex_height/2
self.l_image.set_position(0-tex_width,yloc )
#make the center image visible
self.l_image.set_opacity(255)

def parseKeyPress(self,actor, event):
#do stuff when the user presses a key
#it would be awesome if I could find some documentation regarding clutter.keysyms
if event.keyval == clutter.keysyms.q:
#if the user pressed "q" quit the test
clutter.main_quit()
elif event.keyval == clutter.keysyms.Right:
self.next_image(0)
elif event.keyval == clutter.keysyms.Left:
self.next_image(1)

#direction of 0 means move right, direction 1 means move from right to left
def next_image(self,direction=0):
#clear the behaviour paths
self.lc_behaviour.clear()
self.cr_behaviour.clear()
self.lc_behaviour.remove_all()
self.cr_behaviour.remove_all()
#update the center texture
self.set_center_image()
if direction:
#we need to set the right image
self.set_right_image()
#hide the left image
self.l_image.set_opacity(0)
#adjust the image list index
self.imagelist.increment_index()
#center image moves to the left
(x,y) = self.c_image.get_position()
lc_knot0 = clutter.Knot(x,y)
#what is the destination knot?
lc_knot1 = clutter.Knot(-self.c_image.get_width(),y )
#which texture is moving in the lc?
lc_texture = self.c_image
#right image moves to the left
(x,y) = self.r_image.get_position()
cr_knot0 = clutter.Knot(x,y)
xcenter = self.stage_w/2-self.r_image.get_width()/2
cr_knot1 = clutter.Knot(xcenter,y )
#which texture is moving in the cr?
cr_texture = self.r_image

else:
#we need to set the left image
self.set_left_image()
#hide the right image
self.r_image.set_opacity(0)
#adjust the image list index
self.imagelist.decrement_index()
#left image moves to the center
(x,y) = self.l_image.get_position()
lc_knot0 = clutter.Knot(x,y)
xcenter = self.stage_w/2-self.l_image.get_width()/2
lc_knot1 = clutter.Knot(xcenter,y )
#which texture is moving in the lc?
lc_texture = self.l_image
#center image moves to the right
(x,y) = self.c_image.get_position()
cr_knot0 = clutter.Knot(x,y)
endx = self.stage_w
cr_knot1 = clutter.Knot(endx,y )
#which texture is moving in the cr?
cr_texture = self.c_image

#add the knots to the lc behaviour
self.lc_behaviour.insert_knot(0,lc_knot0)
self.lc_behaviour.insert_knot(1,lc_knot1)
self.lc_behaviour.apply(lc_texture)
#add the knots to the cr behaviour
self.cr_behaviour.insert_knot(0,cr_knot0)
self.cr_behaviour.insert_knot(1,cr_knot1)
self.cr_behaviour.apply(cr_texture)
#start the timeline associated with the behaviours
self.texture_timeline.start()

def create_image_list(self,image_folder):
cwd = os.getcwd()
path_to_image_folder = os.path.join(cwd,image_folder)
#does the folder exist?
if os.path.isdir(path_to_image_folder):
print "image folder: "+path_to_image_folder
self.imagelist = imageList(path_to_image_folder)
#did we find images?
img_count = self.imagelist.get_image_count()
print "Found "+str(img_count)+" images"
if img_count ==0:
self.print_help(image_folder+" does not contain usable images")
else:
self.print_help(image_folder+" is not a directory")

def print_help(self,errormessage=""):
if(errormessage):
print "Error: "+errormessage
print "Usage: "+sys.argv[0]+" /path/to/directory/containing/images"
print "Navigation: use the left and right arrows to view the images"
print ""
sys.exit()
if __name__=="__main__":
#make an imageViewer
imageViewer = imageViewer()


Problems:
1. I was hoping to automatically change a clutter textures height and width by making sure that the texture's "sync-size" property was true and then changing the textures pixbuf. Unfortunately, this didn't work, so I grabbed the height and width the pixbuf itself and adjusted the size of the texture accordingly.
2. Althought it was a minor problem, I spend too much time trying to figure out how to use gstreamer to get the data from my images files and pass the data to a gstvideotexture. As you can see, I ended up using gtk.gdk for image handling.
3. segfaulting on behaviourPath.append_knots(knot1,knot2)

Nifty Clutter:
behaviourPath knots - a knot is an X,Y coordinate that make a path for an object to follow when the object animates. For example, suppose I have a texture at 0,0 and I want to move the texture to 200,100 and then to 50,400. I would make a knot for each coordinate and add the knot to a behaviourPath using append_knots(list of knots) or insert_knot(knot index, knot).
myBehaviourPath.append_knots(knot1,knot2,knot3)
then apply the behavor to the texture and start the timeline associated with the behaviours alpha
myBehaviourPath.append(myTexture)
myTimeline.start()
Booyah! The texture will move from knot1 to knot2 to knot3

Awesome:
Pydoc. I can't believe it took me so long to learn about pydoc: a python documentation tool. Which I found indispensable for figuring out what methods are available in various python modules.
Comments
2008-12-23 Anonymous:
for clutter-0.8 change:

buf = gtk.gdk.pixbuf_new_from_file( self.imagelist.get_index_image() )
self.c_image.set_pixbuf( buf )

to:

self.c_image.set_from_file( self.imagelist.get_index_image() )

===================================
But self.stage.fullscreen() can only maximize the window.
Do you know how to setup a real fullscreen (borderless) window?
2008-12-23 jezra:
Since the fullscreen() function does fill my entire screen when using pyclutter 0.6.x, this may be a bug in the latest branch of clutter.
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
9 minus 1
Answer:
required
2008-05-02
What is pyclutter? Pyclutter is the python binding to the clutter library: a high level OpenGL library for creating animated user interfaces.

OK, so this isn't really a tutorial because I'm not going to go through each line of code and explain what it does. However, there are certain parts of the code that I will give a bit more info about, because I had some problems figuring it out and I'm hoping my experience will help other.

This is not a static "hello world". I know, I broke the rules; but I think this is a good thing. Upon running the script, there will be a "hello" on the screen. Pressing "s" on the keyboard will initiate a switching toggle between "hello" and "world" by animating a change in their opacities. Pressing "q" will quit the app. Check it out
 #!/usr/bin/env python
print "Hello World!"

Ha ha, just kidding.....
#!/usr/bin/env python

import clutter

class clutterTest:
def __init__(self):
#create a clutter stage
self.stage = clutter.Stage()
#set the stage size in x,y pixels
self.stage.set_size(500,200)
#define some clutter colors in rgbo (red,green,blue,opacity)
color_black =clutter.Color(0,0,0,255)
color_green =clutter.Color(0,255,0,255)
color_blue =clutter.Color(0,0,255,255)
#set the clutter stages bg color to our black
self.stage.set_color(color_black)
#we will need to check on the key presses from the user
self.stage.connect('key-press-event', self.parseKeyPress)
#create a clutter label, is there documentation for creating a clutterlabel?
self.label = clutter.Label()
#set the labels font
self.label.set_font_name('Mono 32')
#add some text to the label
self.label.set_text("Hello")
#make the label green
self.label.set_color(color_green )
#put the label in the center of the stage
(label_width, label_height) = self.label.get_size()
label_x = (self.stage.get_width()/2) - label_width/2
label_y = (self.stage.get_height()/2) - label_height/2
self.label.set_position(label_x, label_y)
#make a second label similar to the first label
self.label2 = clutter.Label()
self.label2.set_font_name('Mono 32')
self.label2.set_text("World!")
self.label2.set_color(color_blue )
(label2_width, label2_height) = self.label2.get_size()
label2_x = (self.stage.get_width()/2) - label2_width/2
label2_y = (self.stage.get_height()/2) - label2_height/2
self.label2.set_position(label2_x, label2_y)
#hide the label2
self.label2.set_opacity(0)
#create a timeline for the animations that are going to happen
self.timeline = clutter.Timeline(fps=20,duration=500)
#how will the animation flow? ease in? ease out? or steady?
#ramp_inc_func will make the animation steady
labelalpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
#make some opacity behaviours that we will apply to the labels
self.hideBehaviour = clutter.BehaviourOpacity(255,0x00,labelalpha)
self.showBehaviour = clutter.BehaviourOpacity(0x00,255,labelalpha)
#add the items to the stage
self.stage.add(self.label2)
self.stage.add(self.label)
#show all stage items and enter the clutter main loop
self.stage.show_all()
clutter.main()

def parseKeyPress(self,actor, event):
#do stuff when the user presses a key
#it would be awesome if I could find some documentation regarding clutter.keysyms
if event.keyval == clutter.keysyms.q:
#if the user pressed "q" quit the test
clutter.main_quit()
elif event.keyval == clutter.keysyms.s:
#if the user pressed "s" swap the labels
self.swapLabels()


def swapLabels(self):
#which label is at full opacity?, like the highlander, there can be only one
if(self.label.get_opacity()>1 ):
showing = self.label
hidden = self.label2
else:
showing = self.label2
hidden = self.label
#detach all objects from the behaviors
self.hideBehaviour.remove_all()
self.showBehaviour.remove_all()
#apply the behaviors to the labels
self.hideBehaviour.apply(showing)
self.showBehaviour.apply(hidden)
#behaviours do nothing if their timelines are not running
self.timeline.start()



if __name__=="__main__":
test = clutterTest()


Copy the code and drop it into your favorite text editor.
things I got hung up on....
1. Labels:the pyclutter documentation doesn't reference labels. Fortunately, the pyclutter examples that are included with the pyclutter source code, have a sample of a label
2. Alpha: clutter.alpha is a representation of a value based on a clutter.timeline and a function to determine the value at a given time on the time line. The first function that I used was a sine function that would peak at the midway point and then return to the starting point. So my opacity behavior would go from 0 to 255 and then back to 0, when what I really wanted was to go from 0 to 255.
3. behaviourOpacity: When the behavior transitions the opacity from 255 to 0, the ending opacity is 1, or at least is was the last time I checked. Odd.
4. Determining which key is pressed: I don't know enough about python to be able to print out all of the data in the event object that is sent when there is a "key-press-event". I was trying to print the keys from the event objects dict but nothing was working. Luckily, I stumbles upon the clutter.keysyms doohicky but I haven't found all of the documentation for the keysyms yet. For now, I just use clutter.keysyms.[what key am I looking for] to determine if a specific key is pressed.

That's it for now...
Comments
2009-09-23 kelvan:
doesn't work with python-clutter1.0.0
2009-09-23 jezra:
This example was written for clutter 0.6. Fortunately, the python backtraces make it fairly easy to determine what has changed from 0.6 to 1.0. In this case, it is probably the change of the "Label" object to a "Text" object.
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
9 minus 7
Answer:
required
subscribe
 
2019
2016
2015
2014
2013
2012
2011
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008