pyclutter简易教程

2010-04-25 黄毅

clutter 是一个动画GUI库,基于OpenGL图形加速,设计良好的api,基于GObject体系,和gtk环境良好整好。gnome3.0新的window manager mutter 就是基于这个库开发。

linux 上 3D window manager 由来已久,但是除了游戏,大部分应用程序本身仍然还是使用2D进行渲染。clutter就是希望能够给应用程序提供一个易用的接口,使用3D效果创建新一代的UI。

好用的接口总是让人心旷神怡的, processing 已经让我惊艳过一次,这次 clutter 也不例外。下面就开始我们的 clutter 之旅吧。

因为 clutter 的概念和接口都比较简单,本教程文字介绍并不多,主要通过代码展示clutter的基本概念。里面的代码和截图都是在我的电脑上实地跑出来的。

代码目录: code/clutter-tutorial/

安装

如果你已经是ubuntu10.04的用户,那么clutter已经自带,你只需要再安装一个 pyclutter 的包即可。其他用户可到如下网站下去安装相应的库和相关的依赖:

其他资源:

第一个窗口

images/clutter-tutorial/Screenshot-simple.png

运行结果

#!/usr/bin/python
import clutter
stage = clutter.Stage()
stage.set_title('simple')
stage.set_size(256,256)
stage.set_color(clutter.color_from_string('black'))
stage.show()
stage.connect("destroy", clutter.main_quit)
clutter.main()

首先我们创建了一个 Stage 对象。这里先解释一下什么是 Stage 对象。

在clutter中最重要的一个概念就是 Actor,它是 clutter 处理的基本元素,Actor可以有子Actor,也就是说Actor构成一个树状结构。 而Stage就是这棵树的根节点。在运行的时候,Stage也就代表了整个窗口。

在代码中,我们设置了窗口的标题,大小和背景色,并绑定了一个 destroy 的事件,这样我们点击窗口的关闭按钮时,程序可以正常退出。

下面,我们在这个窗口中展示一些具体内容。

基本元素

这个代码向窗口中添加了一个蓝色的矩形。

images/clutter-tutorial/Screenshot-sqare.png

运行结果

#!/usr/bin/python
import clutter
stage = clutter.Stage()
stage.set_title('sqare')
stage.set_color(clutter.color_from_string('black'))
stage.set_size(256, 256)
sqare = clutter.Rectangle()
sqare.set_color(clutter.color_from_string('blue'))
sqare.set_size(100, 100)
sqare.set_position(50, 50)
stage.add(sqare)
stage.show()
stage.connect("destroy", clutter.main_quit)
clutter.main()

动起来

下面我们来加点有意思的东西:动画。下面的代码可以让多个矩形以不同的速度进行旋转。而且我们顺便加了个鼠标点击事件可以让你通过点击对某个图形进行隐藏。

images/clutter-tutorial/Screenshot-rotate.png

运行结果

#!/usr/bin/python
# coding: utf-8
import clutter
def create_sqare(stage, color):
sqare = clutter.Rectangle()
sqare.set_color(color)
sqare.set_size(100, 150)
# 设置锚点的相对坐标,position将以锚点为基准,
# 旋转的时候也以锚点为中心
sqare.set_anchor_point(50, 75)
sqare.set_position(128, 128)
stage.add(sqare)
return sqare
stage = clutter.Stage()
stage.set_title('rotate')
stage.set_color(clutter.color_from_string('#000000'))
stage.set_size(256, 256)
colors = ['#ccffffaa', '#ffffccaa', '#ffccffaa', '#ffff00aa', '#00ffffaa']
sqares = [create_sqare(stage, clutter.color_from_string(color)) for color in colors]
rotate = 0
def on_new_frame(stage,event,data=None):
global rotate
rotate += 0.3
for i,sqare in enumerate(sqares):
# 围绕Z轴和X轴进行旋转,哈哈,看到3D效果了吧
# 你也可以尝试只围绕 Z 轴旋转,那就是在平面上进行旋转了
sqare.set_rotation(clutter.Z_AXIS, rotate*i,0,0,0)
sqare.set_rotation(clutter.X_AXIS, rotate*i,0,0,0)
# timeline是clutter动画接口的核心
timeline = clutter.Timeline(60)
# 每进入一帧,将调用回调函数
timeline.connect('new-frame', on_new_frame)
# 动画循环播放
timeline.set_loop(True)
timeline.start()
def on_button_press(stage, event, data=None):
# 如果觉得方框太多,点击即可隐藏
selected = stage.get_actor_at_pos(clutter.PICK_ALL, event.x, event.y)
if selected!=stage:
selected.hide()
stage.show()
stage.connect("destroy", clutter.main_quit)
stage.connect("button-press-event", on_button_press)
clutter.main()

组合动画

多创建复杂动画的时候,将逻辑全都塞在一个 timeline 的回调函数里面未免显得臃肿,下面介绍clutter提供的多个timeline并行运行的机制。下面的代码可以让图形在旋转的同时进行缩放。

images/clutter-tutorial/Screenshot-complex.png

运行结果

#!/usr/bin/python
# coding: utf-8
import clutter
def create_sqare(stage, color):
sqare = clutter.Rectangle()
sqare.set_color(color)
sqare.set_size(100, 150)
sqare.set_anchor_point(50, 75)
sqare.set_position(128, 128)
stage.add(sqare)
return sqare
stage = clutter.Stage()
stage.set_title('complex')
stage.set_color(clutter.color_from_string('#000000'))
stage.set_size(256, 256)
colors = ['#ccffffaa', '#ffffccaa', '#ffccffaa', '#ffff00aa', '#00ffffaa']
sqares = [create_sqare(stage, clutter.color_from_string(color)) for color in colors]
rotate = 0
def on_rotate_frame(stage,event,data=None):
global rotate
rotate += 0.3
for i,sqare in enumerate(sqares):
sqare.set_rotation(clutter.Z_AXIS, rotate*i,0,0,0)
sqare.set_rotation(clutter.X_AXIS, rotate*i,0,0,0)
scale = 0
speed = 0.1
def on_scale_frame(stage,event,data=None):
global scale,speed
scale += speed
if scale>1.0:
scale = 1.0
speed = -speed
elif scale<0.0:
scale = 0.0
speed = -speed
scale_amount = scale+1.0
for i,sqare in enumerate(sqares):
# 设置缩放,两个参数代表方框平面上两个维度上的缩放
sqare.set_scale(scale_amount, scale_amount)
rotate_timeline = clutter.Timeline(60)
rotate_timeline.connect('new-frame', on_rotate_frame)
scale_timeline = clutter.Timeline(60)
scale_timeline.connect('new-frame', on_scale_frame)
# score 对象用来管理多个timeline对象的组合
# 组合方式可以是并行,也可以是串行
score = clutter.Score()
score.append(rotate_timeline)
# 两个timeline并行执行
score.append(scale_timeline)
score.set_loop(True)
score.start()
def on_button_press(stage, event, data=None):
# 如果觉得方框太多,点击即可隐藏
selected = stage.get_actor_at_pos(clutter.PICK_ALL, event.x, event.y)
if selected!=stage:
selected.hide()
stage.show()
stage.connect("destroy", clutter.main_quit)
stage.connect("button-press-event", on_button_press)
clutter.main()

Texture

TODO


blog comments powered by Disqus

转载请注明出处,收藏或分享这篇文章到: