Правильный способ создания приложений Gtk3 в Python

Я только начал изучать создание графических приложений на Python. Я решил использовать версию Gtk 3. Согласно (официальному?) Руководству по http://python-gtk-3-tutorial.readthedocs.org/, правильный способ создания приветственного мирового приложения:

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://www.micahcarrick.com/gtk3-python-hello-world.html) я нашел совершенно другое aproach, которое:

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)

Может ли кто-нибудь из участников этой категории сказать мне, каким образом я должен писать приложения Gtk 3 на python в эти дни? Я уже знаком с написанием графических интерфейсов (провел несколько месяцев в Java Swing), чтобы вы могли продолжать использовать такие термины, как события, обратные вызовы и т.д.

Ответ 1

Выбор записи новой программы с помощью GtkApplication или просто GtkWindow зависит от требуемой функциональности и в определенной степени от предполагаемой аудитории.

В большинстве случаев, особенно когда вы все еще изучаете инструментарий, я бы согласился с valmynd, что GtkApplication излишне усложнена. GtkApplication предоставляет множество дополнительных функций, которые вам, вероятно, не нужны или не нужны в небольших приложениях.

Для более крупных, более полных приложений я согласен с Dragnucs, второй подход является превосходным и может обеспечить лучшую интеграцию в среду рабочего стола. Из Цель GNOME: порт в GtkApplication (см. Также GtkApplication):

Портирование приложения для использования GtkApplication имеет неплохие преимущества: GtkApplication обрабатывает инициализацию GTK +, уникальность приложения, управление сеансом, обеспечивает некоторую базовую возможность сценариев и интеграцию оболочек на рабочем столе путем экспорта действий и меню и управляет списком окон верхнего уровня, жизненный цикл которых автоматически привязан к жизненному циклу вашего приложения.

Однако я не согласен с Dragnucs о том, почему подход GtkWindow введен в учебнике. Я склонен думать, что простые примеры с очень маленьким шаблоном более подходят для раздела "Начало работы" в учебниках (но я думаю, что учебник по чтению-docs нужно обновить, чтобы включить хотя бы некоторое упоминание о GtkApplication).

В приложениях, которые я написал, я склонен либо подклассифицировать как GtkApplication, так и GtkWindow или для однократных быстрых и неприятных приложений только подкласс GtkWindow. Ваше решение будет зависеть от потребностей ваших приложений.

Техническая разница: Существует также важное техническое различие между тем, как реализуются два примера. Пример с помощью только GtkWindow создает новый основной цикл Gtk для каждого экземпляра программы. В примере с GtkApplication создается один основной цикл, прикрепленный к первому экземпляру, и каждый последующий вызов run(None) будет запрашивать, чтобы исходный экземпляр создал новое окно (новый экземпляр затем выйдет). Попробуйте открыть два терминала и запустить приложение в каждом окне, обратите внимание, что один терминал будет ждать, пока все окна не будут закрыты, прежде чем снова станут чувствительными. Вы можете изменить это поведение, используя G_APPLICATION_NON_UNIQUE вместо G_APPLICATION_FLAGS_NONE.

Ответ 2

Второй пример кода выглядит излишне сложным для меня, первый выглядит отлично. Автор этого второго учебника установил ссылку на другой, еще более простой пример (Источник):

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, кстати.

Ответ 3

Второй подход лучше. Это делает приложение более интегрированным в рабочий стол и сообщает больше о том, что он делает или должен делать. Он также предоставляет вам больше инструментов для использования с вашим приложением.

Я думаю, что первый подход просто не обновлен или что-то еще. Второй вариант действительно является предпочтительным.

Вы можете видеть, что приложение Gnome-music фактически использует второй подход с использованием Gtk.Application. Все официальные приложения Gnome используют Gtk.Application, и все приложения Gtk также должны использовать его.