一种使用 Python、Gtk 和 Cairo 实现过渡动画的方法?

发布于 2024-11-29 02:15:31 字数 2007 浏览 1 评论 0原文

我看过一些教程

,展示如何使用 PyGtk 创建动画,最好的教程是:

https://cairgraphics。 org/cookbook/animationrotation/

本教程使用 gobject.timeout_add() 设置一些时钟来不断刷新动画。

相反,我想做的是创建有限的动画,我可以通过单击某个按钮或复选框或任何东西来触发它。

例如,我可以有一个带有按钮的窗口和一个绘制有球的绘图区域。 当我点击按钮时,球会上下移动,然后停止。如果我再次单击按钮,球就会重复移动。

在另一种情况下,球可能位于屏幕的左侧。当我切换复选框时,球会向右移动(不是立即,而是过渡移动)。如果我取消选中,球就会回到原来的位置。

我不打算使用纯 Cairo/Gtk 以外的任何东西(没有 Clutter、没有 OpenGL、没有 PyGame),因为我觉得这应该是可能的,并且我想继续学习 Gtk 来做一些(未来的)GUI 技巧简单的单文件脚本。

由于问题是关于更广泛的问题,我认为不需要添加代码,但如果有人觉得更好,我可以编辑这个问题以添加一些代码。

感谢您的阅读和任何帮助!开罗/Gtk 很棒!

编辑:在杰里米·弗洛雷斯(Jeremy Flores)的精确解释之后,我得出了这段代码,它是无用的(每次单击按钮时球都会向右移动,直到从窗口掉下来),但包含构建更多内容的元素有创意且有用的东西。如果有人(包括杰里米)对这段代码有什么话要说,特别是关于删除不必要的部分,我很高兴听到。谢谢!

#!/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()

people

I have seen some tutorials showing how to create animations with PyGtk, the best one being this:

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

This tutorial uses gobject.timeout_add() to set some clock to constantly refresh the animation.

What I wanted to do, instead, is to create FINITE animations, which I could trigger by clicking in some button or checkbox or anything.

For example, I could have a Window with a Button and a DrawingArea with a ball drawn.
When I click the button, the ball would go up and down, and stop. If I click the button again, the ball repeats the move.

In another scenario, the ball could be on the left of the screen. When I toggle a CheckBox, the ball goes (not instantly, but rather moves in a transition) to the right. If I uncheck, the ball comes back to its original position.

I am not planning to use anything else than pure Cairo/Gtk (no Clutter, no OpenGL, no PyGame), because I feel that it should be possible, and I want to go on studying Gtk to do some (future) GUI tricks with simple one-file scripts.

Since the question is about a broader problem, I think it is not needed to add code, but I could edit this question to put some code if anyone feels it would be better.

Thanks for reading and for any help! And Cairo/Gtk is great!

EDIT: after the precise explanation from Jeremy Flores, I came out with this code, which is useless (the ball goes to the right each time the button is clicked, untill falling off the window), but contains the elements upon which to build more creative and useful stuff. If anyone (including Jeremy) has anything to say about this code, specially about removing unnecessary parts, I would very gladly like to hear. Thanks!

#!/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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别把无礼当个性 2024-12-06 02:15:31

gobject.timeout_add() 可用于有限动画。您设置的回调将继续被调用,直到返回 False,此时您的方法将不会再次被调用。

例如,如果您希望一个球的动画持续 5 秒,您将负责确定动画持续了多长时间,然后一旦超过 5 秒,您的方法将返回 False 以结束动画。当您希望动画再次开始时,只需使用 timeout_add 重新注册回调并重置计时器即可。

请参阅: http://www.pygtk.org/ pygtk2reference/gobject-functions.html#function-gobject--timeout-add 了解更多信息。

gobject.timeout_add() can be used for finite animations. The callback you set up will keep being called until it returns False, at which point your method won't be called again.

For example, if you want a ball to be animated for 5 seconds, you would be responsible for determining how long the animation has been going, and then once it has passed 5 seconds, your method would return False to end the animation. When you want the animation to start again, simply re-register the callback with timeout_add and reset your time counter.

See: http://www.pygtk.org/pygtk2reference/gobject-functions.html#function-gobject--timeout-add for more information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文