如何创建一个滑动小部件(GTK+,Quickly)

最近我在Gedit中看到了这个小部件。

enter image description here

它会在你按下Ctrl + F的时候出现。我感兴趣的是如何实现滑动效果。任何建议都将不胜感激。

不明白滑动效果是什么意思。请解释一下“滑动效果”的含义。 - twister_void
@Gaurav_Java 它似乎是从顶部面板下方滑出来的。如果你在 Gedit 中看到它,你会发现按下 'Ctrl + F' 键。 - Ángel Araya
这种效果通常被称为“下拉”,我相信 - 有时菜单也以同样的方式进行动画处理。 - Steve Kroon
@SteveKroon,我找到的都是关于ComboBoxes的内容,对其他小部件没有用。我想。 - Ángel Araya
1我觉得你可以使用CSS过渡属性,但是我不知道如何在CSS中改变定位。浏览gedit的代码,他们似乎使用了一个自定义的视图框架来处理搜索框 http://bazaar.launchpad.net/~vcs-imports/gedit/master-git/view/head:/gedit/gedit-view-frame.c ,然后通过一些戏剧模块(看看bzr)来实现动画效果。不过,我对解析C代码并不擅长。 - Ian B.
1顺便说一句,这个小工具在谷歌浏览器(以及Chromium)中也有。 - Ian B.
好问题。@IanB。在我看来,Google Chrome在这方面似乎没有使用GTK,除非它没有经过大量调整的GTK。我将查看gedit的源代码,希望能找出答案。 - Rafał Cieślak
根据gtkmm文档,有一个名为Gtk::Revealer的类可以完全满足你的需求。老实说,我从未使用过它,所以我不会发表答案。Revealer继承自Gtk::Bin,因此它可以存储一个小部件。此外,还有一个枚举类型,用于配置动画类型,如淡入、向上滑动、向左滑动等。更多信息请参考https://developer.gnome.org/gtkmm/stable/group__gtkmmEnums.html#ga027016b2a3cb48c00420bd5c883d2542 - fnc12
@fnc12 是的,这是在2013年孵化于libgd并上游到GTK+的,此问题及其答案之后;请参阅我的新回答 - underscore_d
4个回答

我使用纯GTK和CSS实现了一个淡出效果。
它只在GTK 3.6版本中有效,我不确定是否可能实现滑入/滑出的效果,但是如果你愿意,可以在launchpad.net/uberwriter上查看源代码。
它通过状态改变和GTK过渡来实现...也许通过高度//宽度也是可能的。
编辑
因为人们显然对我进行了负面评价,所以这里有另一个更详细的解释:
这是我使用的CSS:
GtkLabel:insensitive {
    color: rgba(255,255,255,0);
    transition: 500ms ease-in-out;
}

如果你将这个作为CSS使用(我希望我可以引用自己的解释,如何做到这一点:http://wolfvollprecht.de/blog/gtk-python-and-css-are-an-awesome-combo/),那么你可以使用Gtk.StateFlags来淡化标签。

e.g.:

label.set_state_flags(Gtk.StateFlags.INSENSITIVE, True)
然后你会得到一个透明度为零的过渡。
然而,正如我所注意到的,使用CSS影响布局/宽度的选项并不多,所以我猜它仅限于颜色/透明度等方面。
享受吧。
附注:请注意,这仅适用于Gtk 3.6,自Ubuntu 12.10起。

人们可能对此进行了负投票,因为问题要求一个滑动动画,而您提供的是透明度过渡,这完全不同...所以我不知道为什么有这么多其他人_点赞_。无论如何,现在有GtkRevealer可以同时实现两者;请参阅我的答案 - underscore_d

这样的动画在纯GTK+中是无法实现的。没有机制来处理它。
我快速浏览了gedit的源代码,很明显他们自己处理了这个动画。虽然我没有详细研究与动画相关的代码,因为它相当复杂,但我注意到他们使用了Cairo绘图功能来实现搜索小部件的动画效果。很可能这个小部件通过逐帧移动位置并在单个文本显示区域的叠加层上重新绘制来实现动画效果。
这似乎是最简单的解决方案。(gedit的代码似乎准备了许多共享相同代码基础的动画,因此在简单应用程序中使用其确切方法可能有些过度设计。)
要重现这个效果,您需要:
- 使用自定义小部件来实现您想要滑入/滑出的UI部分。 - 使其对“绘制”事件和定期超时(以重新绘制每一帧动画)做出反应。 - 在其他小部件(或任何需要看起来像在滑动小部件下面的区域)上创建一个透明的叠加层。 - 在这样的叠加层上手动绘制动画小部件。
我想不出任何更简单的解决方案。然而,考虑到gedit开发人员对GTK+的了解可能比其他人少得多,可能没有更简单的方法来实现这样的效果。

似乎你的想法是“最简单的”。我原以为可以通过一些 CSS 的技巧来实现,但是阅读 Gedit 的代码后发现它更像是硬编码并且为了更多的功能而准备的,正如你所说,不仅仅是一个简单的搜索框输入。因此,我将尝试制作一个自定义小部件,并在特定事件中首先移动它(如果可能的话)。感谢你的建议。 - Ángel Araya

你可以使用Gtk.fixed()、GObject.timeout_add和move函数的组合,以下是一个Python示例:
```python #!/usr/bin/python* from gi.repository import Gtk, GObject
class TestWindow(Gtk.Window): def animateImage(self): GObject.timeout_add(150, self.slideImage)
def slideImage(self): self.positionX += 50 if self.positionX > 800: self.fixedWidget.move(self.logo, self.positionX, 200) return True else: return False def __init__(self): Gtk.Window.__init__(self, title='Registration')
self.positionX = 500 self.fixedWidget = Gtk.Fixed() self.fixedWidget.set_size_request(1920, 1080) self.fixedWidget.show()
self.logo = Gtk.Image.new_from_file('picture.png') self.logo.show() self.fixedWidget.put(self.logo, self.positionX, 200)
self.button1 = Gtk.Button('Click me to slide image!') self.button1.show() self.button1.connect('clicked', self.animateImage) self.button1.set_size_request(75, 30) self.fixedWidget.put(self.button1, 750, 750) self.add(self.fixedWidget)
testWindow = TestWindow() testWindow.set_size_request(1920, 1080) testWindow.set_name('testWindow') testWindow.show()
Gtk.main() ```

如今,对于这个问题有一个真正的答案。自从最初提出并回答这个问题以来,用于显示libgd小部件的代码 - 我猜想那时GEdit使用的就是这个 - 已被上游合并到GTK+中作为GtkRevealer

https://developer.gnome.org/gtk3/stable/GtkRevealer.html

GtkRevealer支持各种形式的过渡效果,包括滑动和淡入淡出的基本方向。

所以,现在只需要将要过渡的小部件添加到GtkRevealer中,并使用它的:transition-(type|duration):reveal-child属性即可。


这是一个有用的答案,但我认为最好让人们展示如何在Python+GTK中完成这个任务,以提供现成的解决方案。我发现这里的许多示例都不完整且难以复制,特别是经过了几年之后,没有发布任何能够正常工作过的代码。 - shevy