An introduction to pyclutter (part two)
September 30th, 2007
This tutorial is outdated: it refers to version 0.4 of clutter that now is VERY old.
Last time we learned how to have our first stage drawn, so now it’s time to begin to insert something into that stage.
Let do a summary of what we are going to do in this “lesson”:
- change the stage’s color
- add a rectangle to the stage
- add another rectangle to the stage
The first thing we want to do is to change the stage’s color. This can be done by using the set_color() method of the stage object:
stage.set_color(clutter.color_parse("#00000"))
In this way we have a black stage. But how does it works? The set_color() method needs a ClutterColor object in input, and we can have it by calling the color_parse() function. The color_parse() has the same syntax of pango_color_parse() (a built-in GTK function), so it accepts both hexadecimal specifications of the color (i.e.: #000000 or #000 for black, #FF0000 or #F00 for red) and literal color values like “black” or “red”. Additionally, we can specify a pixel alpha value (the object’s opacity level) by using a hexadecimal specification like #000000FF, where FF is the alpha value. We can specify an alpha value for the stage but it won’t work since the stage hasn’t a alpha layer.
After this, our window will look like this:
Note that now the window became black as we specified. Now that we completed the first goal, it’s time for us to introduce a new clutter object: the rectangle.
A rectangle is made up by the rectangle itself and a border. That said, if we tell clutter to draw a 100x100px rectangle with a 2px border, the resulting rectangle will be 2px + 100px + 2px large.
Now that we had enough theory, we can begin to draw our first rectangle:
import clutter
def main():
stage = clutter.stage_get_default()
stage.set_size(500, 500)
stage.set_color(clutter.color_parse("#000000"))
rect = clutter.Rectangle()
rect.set_position(20, 20)
rect.set_size(200, 300)
rect.set_color(clutter.color_parse("#A02020"))
stage.add(rect)
rect.show()
stage.show()
stage.connect("key-press-event", clutter.main_quit)
clutter.main()
if __name__ == '__main__':
main()
This code will give us this output:
And now it’s time to analyze what we done by looking at the code line per line (I’ll skip the lines that we already seen):
rect = clutter.Rectangle()
In order to draw a rectangle we need an instance of the rectangle object, right? We can get this instance by calling the Rectangle constructor function.
Once we have our rectangle instance, we can make operations like positioning and coloring on it:
rect.set_position(20, 20)
rect.set_size(200, 300)
rect.set_color(clutter.color_parse("#A02020"))
The first line moves the upper left corner of the rectangle at position (20, 20) in the stage. The second and the third line, instead, are functions that we have already seen: both the rectangle’set_size() and set_color() functions works exactly as the stage’s one (we’ll see further in another part of this tutorial why the name and the implementation is the same). Indeed, in this way we can specify both a size and a color for our rectangle.
stage.add(rect)
We drawn our rectangle, but now we need to tell clutter where to put it: this is done by using the add() method of the stage object (if this operation looks useless to you it’s because we still didn’t talked about Groups and Box; we’ll do that another time, now just take this line as is).
The last line of interest is this one:
rect.show()
We’ve already explained in the previous part how the show() method works for the stage: here’s is exactly the same thing.
Now that we have our first rectangle, is time to draw the second one:
import clutter
def main():
stage = clutter.stage_get_default()
stage.set_size(500, 500)
stage.set_color(clutter.color_parse("#000000"))
rect1 = clutter.Rectangle()
rect2 = clutter.Rectangle()
rect1.set_position(20, 20)
rect1.set_size(200, 300)
rect1.set_color(clutter.color_parse("#A02020"))
rect2.set_position(50, 100)
rect2.set_size(350, 300)
rect2.set_color(clutter.color_parse("#FFFFFF50"))
rect2.set_border_width(20)
rect2.set_border_color(clutter.color_parse("blue"))
stage.add(rect1, rect2)
rect1.show()
rect2.show()
stage.show()
stage.connect("key-press-event", clutter.main_quit)
clutter.main()
if __name__ == '__main__':
main()
We’ll obtain this:
(if you see the second rectangle’s border partially drawn, or not drawn at all, you are probably using a version of clutter older than 0.4.2, where a bug in the border generation deny you from having the rectangle shown correctly)
We’ve already discussed many of the functions in the code above, so I’ll quickly jump to the more complex part. First of all, let do a resume of what we do in this script:
- we create the first rectangle named
rect1 - we create the second rectangle named
rect2 - we set up properties for both rectangles (please note that for the second rectangle we specified a pixel alpha value too)
- then we add the rectangle to the stage and show them
The only thing I should explain is the point number four: the add method of a container (a stage, in this case), can have multiple arguments. Indeed, we can tell clutter to add multiple elements to a container. So in our example, we added both rect1 and rect2 in a single line of code instead of having two separate add statements.
After having the actors added to the stage, we show them by calling the show() method on every single actor. This approach works, but sometimes could be more useful (and time saving) to call a special show method on the parent. We’ll discuss this behaviour better when we’ll talk about groups, but by now on I’ll use the show_all() method on the stage in order to show all its children in one line of code.
See you for the next part of this tutorial :)
Nice tutorials…
Would be nice that the third part faces movements… that’s the novelty for post-wimp interfaces…;-P
Comment by eolo999 — October 21st, 2007 at 20:29
Part three (that is almost done) is about groups… for the movements (in clutter they’re achieved by using behaviours) you have to wait for part four :)
Comment by Giuliani Vito, Ivan — October 22nd, 2007 at 1:36
Thanks. Waiting for next parts…
and… what about pyclutter documentation?
Do you have in mind other materials from which to learn?
Comment by edoardo batini alias eolo999 — October 24th, 2007 at 19:43
My intention was to start writing some documentation as soon as I free myself from other (most important) jobs. Actually, I think there aren’t so much docs around about pyclutter. I’d suggest you to have a look at the examples that there are in the source tree. Anyway, I’ll publish the slides of my talk about pyclutter within some days (I think it will be on Monday).
Comment by Giuliani Vito, Ivan — October 25th, 2007 at 23:05