共 1,304 篇文章
共 6,317 篇文章及评论
- Association for Computing Machinery TechNews (ACM)
- Go Parallel! (Dr. Dobbs)
- HPCwire (Tabor Communications, Inc.)
- insideHPC (John West)
- Joe Duffy's Weblog (Microsoft)
- Microsoft Parallel Programming Development Center (Microsoft Germany)
- MultiCoreInfo.com
- scalability.org (Scalable Informatics)
- Software Dev Blog (Intel Germany)
- Soft Talk Blog (Intel United Kingdom)
- The Moth (Microsoft)
使用Moblin进行应用程序开发——Clutter之动画
作者: 方亮 (Intel) (27 篇文章) 日期: 六月 16, 2009 在 2:19 下午
正文开始之前先说几句别的。上月20号发布的Moblin V2 Beta版中,Clutter的版本已经到了0.9,API与clutter 0.8相比有了些变化,两者在API上已不兼容。鉴于pyclutter目前版本依然还是0.8,并且本系列博文更侧重于概念,因此所用的API一律基于clutter 0.8。等clutter 1.0正式版本发布后,我们再来看API的变化。
之前讲了一点有关Actor与Stage的内容,有了演员和舞台,接下来自然而然就要上台表演,也就是这里所谓的动画了。在Clutter的动画中,有三个概念不得不提一下,他们是——Timeline,Alpha和Behaviour。
Timeline,即时间轴,也就是表演的时间段,这个概念我想大家应该都能明白,不多废话了。Behaviour,即行为,也就是表演的内容,比如放大、缩小、旋转、透明化等等均属于行为的范畴。最后讲讲Alpha,这个词挺难翻译的,如果放到表演上来理解,Alpha所指的应该是表演方式。比如同样是将某个Actor放大2倍,通过Alpha可以控制是采用线性放大,加速放大还是减速放大等效果。Alpha其实是一个与总帧数和当前帧相关的函数,它的返回值是一个介于0和ALPHA_MAX之间的数,每当一个新的帧产生时都会调用Alpha函数,通过Alpha函数的返回值来确定当前帧的变化。用户可以自定义Alpha函数,也可以使用clutter提供的一些常用Alpha函数。
一般来说,基于clutter进行动画编程,代码结构通常是这样的:
1. 创建时间轴ClutterTimeline
2. 创建ClutterAlpha
3. 创建ClutterBehaviour
4. 将Behaviour应用到Actor上
5. 启动时间轴
目前Clutter提供的Behaviour包括有Bspline、Ellipse、Depth、Opacity、Path、Rotate和Scale。如果用户觉得这些Behaviour无法满足应用的需求,可以通过实现自定义Behaviour或者使用Timeline的new-frame事件来制作自定义的动画效果。
回到以前使用的demo 程序——照片浏览器上来,这次要添加的功能是相片的正中显示。之前照片是以随机方位和角度铺在桌面上,现在通过双击照片,图片将以动画的形式移至窗口正中并转至0度。单击正中显示照片将使图片以动画形式回到原先的位置。
代码如下:
#!/usr/bin/python
import sys
import os
import random
import clutter
STAGE_WIDTH=1024
STAGE_HEIGHT=768
Dragging = False
DraggingPhoto = None
Center = False
pic_list = []
timeline = None
alpha = None
p_behavior = None
r_behavior = None
class Photo:
'''Photo class'''
border_width = 10
def __init__(self, path, stage):
self.stage = stage
self.path = path
self.x = 0
self.y = 0
self.degree = 0
self.drag_start_x = 0
self.drag_start_y = 0
self.pic = clutter.Texture()
self.pic.set_from_file(path)
self.width = self.pic.get_width()+2*Photo.border_width
self.height = self.pic.get_height()+2*Photo.border_width
self.frame = clutter.Rectangle()
self.frame.set_color(clutter.Color(0xff, 0xff, 0xff, 0xff))
self.frame.set_position(self.x, self.y)
self.frame.set_size(self.width, self.height)
self.group = clutter.Group()
self.group.add(self.frame)
self.group.add(self.pic)
self.pic.set_position(Photo.border_width, Photo.border_width)
self.stage.add(self.group)
self.group.set_reactive(True)
self.group.connect("button-press-event", self.on_button_press)
self.group.connect("button-release-event", self.on_button_release)
self.group.connect("motion-event", self.on_motion)
def set_random_position(self):
stage_width = self.stage.get_width()
stage_height = self.stage.get_height()
left = random.randint(0, stage_width)
top = random.randint(0, stage_height)
degree = random.randint(0, 360)
self.set_position(left, top, degree)
def set_position(self, x, y, degree):
self.x = x
self.y = y
self.degree = degree
self.group.set_position(x, y)
self.group.set_rotation(clutter.Z_AXIS, degree, self.width/2, self.height/2, 0)
def on_button_press(self, actor, event):
global Dragging, DraggingPhoto, Center, timeline, alpha, p_behavior, r_behavior
if event.button == 1 and event.click_count == 2 and Center == False:
self.group.raise_top()
for pic in pic_list:
pic.group.set_reactive(False)
self.group.set_reactive(True)
timeline = clutter.Timeline(30, 30)
alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
tx = int((STAGE_WIDTH-self.width)/2)
ty = int((STAGE_HEIGHT-self.height)/2)
knots=((self.x, self.y), (tx, ty),)
p_behavior = clutter.BehaviourPath(alpha, knots)
p_behavior.apply(self.group)
r_behavior = clutter.BehaviourRotate(clutter.Z_AXIS, self.degree, 0, alpha, True)
r_behavior.set_center(self.width/2, self.height/2, 0)
r_behavior.apply(self.group)
timeline.start()
Center = True
return True
if event.button == 1 and event.click_count == 1 and Center == True:
for pic in pic_list:
pic.group.set_reactive(True)
timeline = clutter.Timeline(30, 30)
alpha = clutter.Alpha(timeline, clutter.ramp_dec_func)
tx = int((STAGE_WIDTH-self.width)/2)
ty = int((STAGE_HEIGHT-self.height)/2)
knots=((self.x, self.y), (tx, ty),)
p_behavior = clutter.BehaviourPath(alpha, knots)
p_behavior.apply(self.group)
r_behavior = clutter.BehaviourRotate(clutter.Z_AXIS, self.degree, 0, alpha, True)
r_behavior.set_center(self.width/2, self.height/2, 0)
r_behavior.apply(self.group)
timeline.start()
Center = False
return True
if event.button == 1 and Dragging == False and Center == False:
Dragging = True
DraggingPhoto = self
self.drag_start_x = event.x
self.drag_start_y = event.y
self.group.raise_top()
return True
return False
def on_motion(self, actor, event):
global Dragging, DraggingPhoto
if event.modifier_state & clutter.BUTTON1_MASK and Dragging == True and DraggingPhoto == self:
dist_x = event.x - self.drag_start_x
dist_y = event.y - self.drag_start_y
self.group.move_by(dist_x, dist_y)
self.drag_start_x = event.x
self.drag_start_y = event.y
return True
return False
def on_button_release(self, actor, event):
global Dragging, DraggingPhoto
if event.button == 1:
Dragging = False
DraggingPhoto = None
return True
return False
def main(args):
if len(args) < 2:
print "The number of arguments is less than 2!"
return -1
path=args[1]
if not os.path.exists(path):
print path, "doesn't exist!"
return -1
stage = clutter.Stage()
stage.set_size(STAGE_WIDTH, STAGE_HEIGHT)
stage.set_color(clutter.Color(0x00, 0x00, 0x00, 0x00))
stage.connect("destroy", clutter.main_quit)
if not path.endswith(os.sep):
path+=os.sep
filelist = os.listdir(path)
for item in filelist:
pic=Photo(path+item, stage)
pic.set_random_position()
pic_list.append(pic)
stage.show_all()
clutter.main()
if __name__ == '__main__':
main(sys.argv)
分类: 移动技术
标签:Animation, Clutter, Moblin
如需了解英特尔软件产品相关的性能和优化选项,请参阅优化注意事项.
评论 (16)
| 2009年06月19日 00:47
1 | 好 |
| 2009年06月20日 01:49
孙常虹 | 很不错 |
| 2009年06月20日 01:49
孙常虹 | 很不错 |
| 2009年06月20日 01:49
iii | 很不错 |
| 2009年06月20日 20:47
chxu | 不错 |
| 2009年06月21日 04:29
shisulong | ding hao |
| 2009年06月21日 21:05
的法国 | 阿大使馆的试过 |
| 2009年06月23日 07:40
lgh | 顶,谢谢了 |
| 2009年06月23日 21:57
太子 | 很好 可以用用 |
| 2009年06月24日 00:31
wang | feichang hao a ,xiexie a a |
| 2009年06月25日 20:53
wm |
学习它接近一个月了,我发现clutter没有直接能用的button,input-box。请问怎么用clutter封装一个按钮类和文 本框输入类呢? 急??? |
| 2009年06月25日 21:07
方亮 (Intel)
|
clutter与传统的UI库如GTK相比似乎更加底层一些,因此其中的控件类型很少。没有button,inputbox倒是有的,呵呵 。在Moblin.org上有个项目叫NBTK,引用下官方描述,呵呵。 “The Netbook Toolkit is a GUI toolkit, using Clutter and is optimised for the Moblin netbook experience. It consists of various classes useful for building UIs such as Buttons, Tooltips, Scrollbars and others. It also supports styling through CSS stylesheets.” 地址是http://moblin.org/projects/netbook-toolkit-nbtk。目前暂时还没有在线文档,文档都打在源码包里。有兴趣的话可以去看一看。 |
| 2009年07月01日 23:57
wm111
|
非常感谢! 因为现在项目需要用clutter来做,所以会有很多问题摆在眼前,头都大了,input-box我还是用一个矩形,一个text加入到一 个group里面来实现的,只是封装起来了,还得处理些东东,不知道这样做可行不?还得请多多指教? |
| 2009年07月02日 00:14
方亮 (Intel)
| to wm111: 即使可行也太麻烦了……ClutterEntry是一个单行的编辑框,应该能符合你的要求。 |
| 2009年07月02日 07:20
wm111
| 我用的是clutter-0.9.2版本,ClutterEntry好像都被ClutterText所能代替,并且单用这个是没有输入框的 边框的,功能倒可以实现,能否有什么例子呢?关于input-box,button. |


grsh