用Python、Gtk和Cairo动画过渡的方法?

1 投票
1 回答
5450 浏览
提问于 2025-04-16 23:19

大家好

我看到一些教程在讲怎么用PyGtk制作动画,其中最好的一个是这个:

https://cairographics.org/cookbook/animationrotation/

这个教程使用了 gobject.timeout_add() 来设置一个时钟,不断刷新动画。

不过我想做的是有限的动画,也就是说我希望能通过点击按钮、复选框或其他东西来触发动画。

举个例子,我可以有一个窗口,里面有一个按钮和一个绘图区域,绘制了一个球。点击按钮后,球会上下移动,然后停下来。如果我再点击一次,球就会重复这个动作。

在另一个场景中,球可能在屏幕的左边。当我切换复选框时,球会(不是瞬间,而是慢慢移动)向右移动。如果我取消勾选,球就会回到原来的位置。

我不打算使用其他任何东西,只想用纯粹的Cairo/Gtk(不使用Clutter、OpenGL或PyGame),因为我觉得这样是可行的,我也想继续学习Gtk,以便将来用简单的一文件脚本做一些GUI的小把戏。

由于这个问题涉及的内容比较广泛,我觉得不需要添加代码,但如果有人觉得加代码会更好,我可以编辑这个问题来放一些代码。

谢谢大家的阅读和帮助!Cairo/Gtk真棒!

编辑:在Jeremy Flores的详细解释后,我写出了这段代码,虽然没什么用(每次点击按钮球都会向右移动,直到掉出窗口),但包含了一些可以用来构建更有创意和实用的东西的元素。如果有人(包括Jeremy)对这段代码有任何意见,特别是关于去掉不必要的部分,我非常乐意听取。谢谢!

#!/usr/bin/env python
import gtk, gobject
from math import pi

class Canvas(gtk.DrawingArea):
    def __init__(self):
        super(Canvas, self).__init__()
        self.connect("expose_event", self.expose)
        self.set_size_request(400,400)

        self.x = 20
        self.y = 20

        self.counter = 0

    def movealittle(self):
        self.x += 1
        self.counter += 1
        self.queue_draw()
        if self.counter <= 20:
            return True
        elif self.counter > 20:
            self.counter = 0
            return False

    def expose(self, widget, event):
        cr = widget.window.cairo_create()
        rect = self.get_allocation()

        w = rect.width
        h = rect.height

        cr.arc(self.x, self.y, 10, 0, 2*pi)
        cr.fill()

def runanimation(widget):
    gobject.timeout_add(5, canvas.movealittle)
    print "runanimation call"

button = gtk.Button("Move")
button.connect("clicked", runanimation)

window = gtk.Window()
canvas = Canvas()
panel = gtk.VBox()
window.add(panel)
panel.pack_start(canvas)
panel.pack_start(button)
window.set_position(gtk.WIN_POS_CENTER)
window.show_all()
gtk.main()

1 个回答

4

gobject.timeout_add() 可以用来做有限的动画。你设置的回调函数会一直被调用,直到它返回 False,这时你的方法就不会再被调用了。

举个例子,如果你想让一个球动画持续 5 秒钟,你需要自己去判断动画已经进行了多长时间,然后一旦超过 5 秒,你的方法就返回 False 来结束动画。当你想要重新开始动画时,只需再次用 timeout_add 注册回调,并重置你的时间计数器。

想了解更多信息,可以查看这个链接:http://www.pygtk.org/pygtk2reference/gobject-functions.html#function-gobject--timeout-add

撰写回答