An introduction to pyclutter (part three)

This tuto­r­ial is out­dated: it refers to ver­sion 0.4 of clut­ter that now is VERY old.

Last time we have seen how to draw the (maybe) most basic shape of clut­ter: the rec­tan­gles. We also posi­tioned them together in the stage, and said (in part one) that the stage is a spe­cial kind of container.

Today it’s time to explain better what groups are and how to use them, so I’ll intro­duce to you the Clut­ter­Group and the ClutterHBox/ClutterVBox.

In the first part of this tuto­r­ial we said that the stage is a top level “window” on which child actors are placed and manip­u­lated. That’s cor­rect, but we also said that a stage is a spe­cial kind of con­tainer. Con­tainer, but it is self explana­tory, con­tains objects: in the clutter’s case, these objects can be other con­tain­ers or actors.

If you have some expe­ri­ence with GTK, you know that GTK uses HBox and VBox for plac­ing the wid­gets respec­tively hor­i­zon­tally and ver­ti­cally. Clut­ter has the same con­cept with Clut­ter­HBox and Clut­ter­VBox but, since clut­ter uses 3D effects, we also have a depth dimen­sion, and we must be able to handle it in some way. Here comes the Clut­ter­Group: it con­tains objects exactly like HBox/VBox, but they’re not added sequen­tially hor­i­zon­tally or ver­ti­cally, they’re added one up the other. Addi­tion­ally, with Clut­ter­Groups, we can use the rel­a­tive posi­tion­ing (we’ll see how later).

But before to talk about groups, it’s better to talk about HBox/VBox. I already said that HBox or VBox are used to place actors (or even other con­tain­ers) sequen­tially. That said, if we add a label to a HBox and then we add a rec­tan­gle, the label and the rec­tan­gle will be placed sequen­tially start­ing from left.

Maybe it’s better to see this behav­iour directly in action:

import clutter

def main():
    stage = clutter.stage_get_default()
    stage.set_size(420, 200)
    stage.set_color(clutter.color_parse("#FFF"))

    hbox = clutter.HBox()
    hbox.set_position(10, 10)
    rect_h1 = clutter.Rectangle()
    rect_h1.set_size(200, 50)
    rect_h1.set_color(clutter.color_parse("#FF0000"))
    rect_h2 = clutter.Rectangle()
    rect_h2.set_size(200, 50)
    rect_h2.set_color(clutter.color_parse("#800000"))
    rect_h2.set_border_width(1)
    rect_h2.set_border_color(clutter.color_parse("#000000"))

    vbox = clutter.VBox()
    vbox.set_position(10, 80)
    rect_v1 = clutter.Rectangle()
    rect_v1.set_size(200, 50)
    rect_v1.set_color(clutter.color_parse("#00FF00"))
    rect_v2 = clutter.Rectangle()
    rect_v2.set_size(200, 50)
    rect_v2.set_color(clutter.color_parse("#008000"))
    rect_v2.set_border_width(1)
    rect_v2.set_border_color(clutter.color_parse("#000000"))

    rect_h1.show()
    rect_h2.show()
    rect_v1.show()
    rect_v2.show()
    hbox.add(rect_h1, rect_h2)
    vbox.add(rect_v1, rect_v2)
    stage.add(hbox, vbox)

    hbox.show_all()
    vbox.show_all()
    stage.show_all()

    stage.connect("key-press-event", clutter.main_quit)
    clutter.main()

if __name__ == '__main__':
    main()

The above code will pro­duce this:

Example 05: HBox and VBoxes

You may ask your­self why we use mul­ti­ple show() instead of having a single show_all() on the stage. The reason is that show_all() doesn’t recurse inside a Group because you might be hiding some of the actors inside that group for a later use. Anyway, it’s pos­si­ble to sub­class a clutter.Group and over­ride the show_all() method so it recurse inside all its chil­dren, but that’s a bit more advanced topic that I hope I’ll be able to cover in another part of the tutorial.

As you can see, the rec­tan­gles have been placed sequen­tially in hor­i­zon­tal (for the HBox) or ver­ti­cal (for the VBox) direc­tion. In this way we can build a basic inter­face, since we can have nested boxes, that said HBoxes that con­tains other HBoxes or VBoxes (this is true for VBox too, obvi­ously):

import clutter

def main():
    stage = clutter.stage_get_default()
    stage.set_size(420, 200)
    stage.set_color(clutter.color_parse("#FFF"))

    hbox = clutter.HBox()
    hbox.set_position(10, 10)
    rect_h1 = clutter.Rectangle()
    rect_h1.set_size(200, 50)
    rect_h1.set_color(clutter.color_parse("#FF0000"))

    vbox = clutter.VBox()
    vbox.set_position(10, 80)
    rect_v1 = clutter.Rectangle()
    rect_v1.set_size(200, 50)
    rect_v1.set_color(clutter.color_parse("#00FF00"))
    rect_v2 = clutter.Rectangle()
    rect_v2.set_size(200, 50)
    rect_v2.set_color(clutter.color_parse("#008000"))
    rect_v2.set_border_width(1)
    rect_v2.set_border_color(clutter.color_parse("#000000"))

    rect_h1.show()
    rect_v1.show()
    rect_v2.show()
    vbox.add(rect_v1, rect_v2)
    hbox.add(rect_h1, vbox)
    stage.add(hbox)

    hbox.show_all()
    vbox.show_all()
    stage.show_all()

    stage.connect("key-press-event", clutter.main_quit)
    clutter.main()

if __name__ == '__main__':
    main()

It works in this way:

Example 06: nested HBox and VBoxes

Let do a step back: we intro­duced the set_​position method pre­vi­ously, but we didn’t explained exten­sively how this method works. The set_​position set the spec­i­fied actor’s posi­tion to the coor­di­nates rel­a­tives to its father con­tainer. So, if we don’t have any con­tainer it reverts to the stage, that is the father of all the childs in a window (and we have absolute posi­tion­ing), oth­er­wise it will set the actor’s posi­tion to the first father it finds. Let see this scheme to clar­ify a bit:

A scheme illusrtating the relative and absolute positionment

Groups shares most of the prop­er­ties of HBox and VBox, but instead of plac­ing the ele­ments hor­i­zon­tally or ver­ti­cally, it posi­tions them on the z-axis (it put the actors one up the other). In this way we can also have a con­tainer that help us in achiev­ing the rel­a­tive posi­tion­ing:

import clutter

def main():
    stage = clutter.stage_get_default()
    stage.set_size(500, 500)
    stage.set_color(clutter.color_parse("#FFF"))

    rect1, rect2, rect3 = clutter.Rectangle(), clutter.Rectangle(), clutter.Rectangle()
    group1, group2, group3 = clutter.Group(), clutter.Group(), clutter.Group()

    group1.add(rect1, group2)
    group2.add(rect2, group3)
    group3.add(rect3)

    group1.set_position(100, 100)
    group2.set_position(100, 100)
    group3.set_position(100, 100)

    rect1.set_position(0, 0)
    rect2.set_position(0, 0)
    rect3.set_position(0, 0)

    rect1.set_size(150, 150)
    rect2.set_size(150, 150)
    rect3.set_size(150, 150)

    rect1.set_color(clutter.color_parse("#FF000090"))
    rect2.set_color(clutter.color_parse("#00FF0090"))
    rect3.set_color(clutter.color_parse("#0000FF90"))

    stage.add(group1)

    stage.show_all()
    group1.show_all()
    group2.show_all()
    group3.show_all()

    stage.connect("key-press-event", clutter.main_quit)
    clutter.main()

if __name__ == '__main__':
    main()

With the above code, we’ll posi­tion each group rel­a­tively to its father. Only the first group will have the stage as father, all the others are rel­a­tive posi­tioned to the pre­vi­ous stage.

Example 07: groups

That’s all for today :)

  1. Great tuto­r­ial. So..when can we expect part 4? :)

  2. I do really hope before the end of the year… I’ve been quite busy ulti­mately, but the part 4 is on the way :)

  3. I know this is a com­pli­cated idea, but this is one of the few places that I can find that is doing work with pyclut­ter.

    I was won­der­ing how I can extend an actor? I found a C Tuto­r­ial about clut­ter and they showed how to create a Tri­an­gle­Ac­tor, I was won­der­ing how hard this would be for pyclut­ter?

    Thanks for any help you can give.

  4. I’m not sure that this kind of stuff can be done with pyclut­ter. For that you should do your cpython exten­sion. Anyway, I have to check since a lot of new stuff joined clut­ter 0.6 and I’m still too busy to look at the improve­ments that the clut­ter staff done.

  5. This code doesn’t seem to work with clut­ter 0.6.

  6. yes, it doesn’t work on py clut­ter 0.6 :

    hbox = clutter.HBox()
    Attrib­u­t­eEr­ror: ‘module’ object has no attribute ‘HBox’

    where are this boxes defined?

    Thanks! this tuto­ri­als are great!

  7. Yes, the tuto­ri­als are out­dated, they’re based upon clut­ter 0.4 (and since then too many things have changed). I should add a note about this, anyway…

  8. Great tuto­ri­als! Thanks for taking time to put these together … hoping you’ll be able to extend them as well. These are great for those of us just learn­ing ..

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">