在Python中构建Gtk3应用程序的正确方法

时间:2014-01-03 16:09:30

标签: python gtk3

我刚开始学习如何在Python中创建GUI应用程序。我决定使用Gtk版本3。 根据{{​​3}}上的(官方?)教程,构建hello world应用程序的正确方法是:

from gi.repository import Gtk

class MyWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_default_size(200, 100)
        self.connect('destroy', Gtk.main_quit)
        self.show_all()

MyWindow()
Gtk.main()

在其他教程(http://python-gtk-3-tutorial.readthedocs.org/)中,我找到了完全不同的方法:

from gi.repository import Gtk, Gio

class HelloWorldApp(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id="apps.test.helloworld",
                                 flags=Gio.ApplicationFlags.FLAGS_NONE)
        self.connect("activate", self.on_activate)

    def on_activate(self, data=None):
        window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
        window.set_title("Gtk3 Python Example")
        window.set_border_width(24)
        label = Gtk.Label("Hello World!")
        window.add(label)
        window.show_all()
        self.add_window(window)

if __name__ == "__main__":
    app = HelloWorldApp()
    app.run(None)

这个类别中有经验的人能告诉我这些天我应该以什么方式在python中编写Gtk 3应用程序?我已经熟悉编写GUI(在Java的Swing中花了几个月),所以你可以继续使用诸如事件,回调等术语。

3 个答案:

答案 0 :(得分:14)

选择使用GtkApplication或GtkWindow编写新程序取决于您需要的功能,以及某种程度上的目标受众。

对于大多数情况,尤其是当你还在学习工具包时,我倾向于同意valmynd认为GtkApplication不必要地复杂化。 GtkApplication提供了许多额外的功能,您可能在较小的应用程序中不需要或不需要。

对于更大,更完整的应用程序,我同意Dragnucs,第二种方法更优越,可以更好地集成到桌面环境中。来自GNOME Goal: Port to GtkApplication(另请参阅GtkApplication文档):

  

将应用程序移植到使用GtkApplication有很好的好处:   GtkApplication处理GTK +初始化,应用程序唯一性,会话管理,通过导出操作和菜单提供一些基本的脚本和桌面shell集成,并管理一个顶级窗口列表,其生命周期自动与应用程序的生命周期相关联。

但是我不同意Dragnucs关于为什么在教程中引入GtkWindow方法。我倾向于认为具有非常少的样板的简单示例更适合于教程入门部分(但是,我确实认为read-the-docs教程需要更新以包括至少一些提及GtkApplication)。

在我编写的应用程序中,我倾向于将GtkApplication和GtkWindow子类化,或者单个窗口快速和讨厌的应用程序只是GtkWindow的子类。您的决定将取决于您的应用需求。

技术差异:两个示例的实现方式之间也存在重要的技术差异。仅使用GtkWindow的示例为程序的每个实例创建一个新的Gtk主循环。 GtkApplication的示例创建了一个附加到第一个实例的主循环,并且每次对run(None)的后续调用都将请求原始实例创建一个新窗口(然后新实例将退出)。尝试打开两个终端并在每个窗口中运行应用程序,注意一个终端将等待所有窗口关闭,然后再次变得敏感。您可以使用G_APPLICATION_NON_UNIQUE代替G_APPLICATION_FLAGS_NONE来更改此行为。

答案 1 :(得分:6)

第二个代码示例看起来不必要复杂,第一个看起来非常好。该第二个教程的作者已经链接到另一个更简单的例子(Source):

from gi.repository import Gtk

window = Gtk.Window(title="Hello World")
window.connect("destroy", lambda w: Gtk.main_quit())
window.add(Gtk.Label("Hello World!"))
window.show_all()

Gtk.main()

这两种方法都没有错。您可以使用所有默认小部件,而不是子类化任何内容,如上例所示。或者你可以子类化某些小部件,主要是为了给你的代码一个很好的结构,并最终有可重用的自定义/修改小部件。这完全取决于你。

这同样适用于Qt和许多其他GUI框架,顺便说一句。

答案 2 :(得分:5)

第二种方法更好。它使应用程序更加集成到桌面中,并更多地了解它的功能或意图。它还为您提供了更多可用于您的应用程序的工具。

我认为第一种方法不是最新的或类似的东西。第二个是真正的首选方式。

您可以看到应用程序Gnome-music实际上正在使用second approach和Gtk.Application用法。所有官方Gnome应用程序都使用Gtk.Application,所有Gtk应用程序也应该使用它。