Skillversitas

Choosing PyGTK vs the Modern Stack

The choice is the one a developer meets when starting a Python GUI project or maintaining an old one: the PyGTK/GTK 2 stack (the binding this tutorial taught) or the modern stack (PyGObject on GTK 3 or GTK 4, and the other Python GUI options - Tkinter, PyQt/PySide, the web-based). The decision is not the features (all of them build a window with buttons) - it is the support horizon (the libraries the target systems ship), the ecosystem (the packages, the theming, the platform integration), and the app's own history (the existing code, the team's familiarity). This chapter lays out the options with their current status, the decision criteria, the migration path from PyGTK, and the recommendation by case - the maintained legacy app, the new app, the cross-platform app.

The Options and Their Status

# the Python GUI options, with the stack each is:

# 1. PyGTK (import gtk) - GTK+ 2, the binding this tutorial:
#    status: MAINTENANCE - the last release line (2.24.11),
#    the GTK 2 libraries still shipped on many systems but
#    leaving the newer distros; no new features
# 2. PyGObject + GTK 3 (gi, Gtk 3.0) - the direct successor:
#    status: STABLE, the current GTK 3 desktops; the same
#    architecture as PyGTK, the introspection binding
# 3. PyGObject + GTK 4 (gi, Gtk 4.0) - the current GTK:
#    status: ACTIVE, the GNOME 40+ desktops; the render
#    model changed (the snapshot, no expose), the CSD default
# 4. Tkinter (the standard library) - the built-in, no dep:
#    status: STABLE but basic - the standard-library toolkit,
#    the limited theming, the no-native-look on the desktops
# 5. PyQt / PySide (Qt) - the commercial-grade toolkit:
#    status: ACTIVE, the cross-platform, the rich widgets,
#    the LGPL (PySide) / the dual (PyQt) licensing
# 6. the web-based (the pywebview, the electron-in-python) -
#    the HTML/CSS UI in a native window: the web stack, the
#    the browser engine, the web dev model

# the table the decision reads: the support horizon, the
# ecosystem, the platform integration, the licensing, the
# the existing code - the criteria, not the features

The options are the six, and their status is the first column of the decision. PyGTK is the maintenance binding - the last release line, the GTK 2 libraries still present on many systems but leaving the newer distributions, no new features, the stack this tutorial taught for the reason that a large installed base runs on it. PyGObject on GTK 3 is the direct successor - the stable, the current GTK 3 desktops, the same architecture as PyGTK with the introspection binding, the migration the transition chapter mapped. PyGObject on GTK 4 is the active current - the GNOME 40+ desktops, the render model changed (the snapshot-based render, the draw replacing the expose), the client-side decorations the default. Tkinter is the standard-library option - no dependency, the basic toolkit, the limited theming, the no-native-look. PyQt/PySide is the commercial-grade cross-platform - the rich widget set, the LGPL (PySide) or the dual (PyQt) licensing. The web-based is the HTML/CSS UI in a native window. The decision reads the status and the ecosystem, not the feature list, because the features are close and the support horizon is not.

The Decision Criteria

# the criteria, in the order the decision weights them:

# 1. the SUPPORT HORIZON - the libraries the target systems
#    will ship over the app's life:
#    - the targets are the current GNOME (GTK 3/4 desktops):
#      the PyGObject stack - the GTK 2 libraries are leaving
#    - the targets are the legacy systems that ship GTK 2:
#      the PyGTK is still viable (the maintenance, not the
#      development, stack)
#    - the targets are cross-platform (the Windows, the macOS,
#      the Linux): the PyQt/PySide (the Qt's cross-platform)
#      or the web-based (the browser engine's)
# 2. the ECOSYSTEM - the packages, the theming, the platform
#    integration the app needs:
#    - the native GNOME look: the GTK stack (the theme, the
#      icons, the platform integration are the desktop's)
#    - the rich widget set + the cross-platform: the Qt
#    - the web dev model + the shared frontend: the web-based
# 3. the EXISTING CODE - the app's history:
#    - the PyGTK app: the migration to PyGObject/GTK 3 is the
#      incremental path (the architecture carries, the spelling
#      changes) - the cheapest evolution
#    - the new app: the start is the decision (no history to
#      weigh) - the support horizon and the ecosystem choose
# 4. the TEAM - the familiarity: the team that knows GTK
#    stays on the GTK line (the PyGTK -> PyGObject is the
#    continuity); the team that knows Qt or the web stays
#    there - the learning cost is a real criterion

The criteria are the four, weighted. The support horizon is the first: the libraries the target systems will ship over the app's life decide the viable stacks - the current GNOME desktops point to the PyGObject stack (the GTK 2 libraries are leaving), the legacy GTK 2 systems keep the PyGTK viable (the maintenance stack), and the cross-platform targets point to the Qt or the web-based (the GTK is the Linux desktop's toolkit, not the cross-platform one). The ecosystem is the second: the native GNOME look is the GTK stack's (the theme, the icons, the platform integration are the desktop's), the rich widget set plus the cross-platform is the Qt's, and the web dev model plus the shared frontend is the web-based's. The existing code is the third: the PyGTK app's cheapest evolution is the migration to PyGObject/GTK 3 (the architecture carries, the spelling changes - the transition chapter's map), and the new app's start is the unconstrained decision the horizon and the ecosystem make. The team is the fourth: the familiarity is a real cost, and the team that knows GTK stays on the GTK line (the PyGTK-to-PyGObject continuity), the team that knows Qt or the web stays there. The criteria are the decision, and the recommendation by case is the application of them.

The Recommendation by Case

# the cases, with the recommendation:

# CASE 1: the maintained PyGTK app, the targets moving to
#         the GTK 3 desktops
#   -> MIGRATE to PyGObject/GTK 3: the incremental path
#      (the import + the namespace, the stock-to-icon, the
#      gtkrc-to-CSS), the architecture unchanged. the GTK 2
#      libraries leaving the distros is the deadline.
#   -> the GTK 4 migration is the NEXT step after the 3,
#      when the app's features need the 4 (the CSD, the new
#      render) - not a two-version jump in one project

# CASE 2: the new app, the native Linux/GNOME desktop
#   -> PyGObject/GTK 3 (or the 4, for the current desktops):
#      the native look, the platform integration, the active
#      stack. the GTK 4 for the new app on the current GNOME;
#      the GTK 3 for the app that targets the broader 3 desktops

# CASE 3: the new app, the cross-platform (Win/mac/Linux)
#   -> PyQt/PySide (the Qt's cross-platform, the rich widgets,
#      the mature ecosystem) or the web-based (the shared
#      frontend, the web dev model). the GTK is not the
#      cross-platform choice (the toolkit is the Linux
#      desktop's)

# CASE 4: the small utility, the no-dependency requirement
#   -> Tkinter (the standard library, the install-free) - the
#      basic toolkit is the trade for the zero dependency

# CASE 5: the stable PyGTK app, the targets that ship GTK 2
#   -> STAY on PyGTK (the maintenance is acceptable) - the
#      migration is a project the app does when the targets
#      force it, not before

The cases are the five, and the recommendation is the criteria applied. The maintained PyGTK app on the targets moving to the GTK 3 desktops migrates to PyGObject/GTK 3 - the incremental path (the import and the namespace, the stock-to-icon, the gtkrc-to-CSS), the architecture unchanged, the GTK 2 libraries' departure the deadline - and the GTK 4 migration is the next step after the 3, when the features need it, not a two-version jump. The new app on the native Linux/GNOME desktop is the PyGObject stack (the GTK 4 for the current GNOME, the GTK 3 for the broader 3 desktops) - the native look and the platform integration. The new cross-platform app is the PyQt/PySide (the Qt's cross-platform, the rich widgets) or the web-based (the shared frontend), because the GTK is the Linux desktop's toolkit, not the cross-platform one. The small no-dependency utility is the Tkinter (the standard library, the install-free, the basic toolkit the trade). And the stable PyGTK app on the targets that ship GTK 2 stays on PyGTK - the maintenance is acceptable, and the migration is the project the targets force, not the one the app starts before the need. The recommendation is the criteria, and the through-line is the one the tutorial holds: the GTK architecture learned on PyGTK is the architecture of the modern GTK stack, and the choice is the support horizon and the ecosystem, not the features.

The Working Rules

  • The support horizon is the first criterion. The libraries the targets will ship decide the viable stacks - the GTK 2 leaving the distros is the PyGTK app's deadline, and the cross-platform targets are the Qt or the web-based, not the GTK.
  • The PyGTK app's evolution is the PyGObject migration. The architecture carries (the signals, the main loop, the containers, the models), the spelling changes (the namespace, the stock-to-icon, the gtkrc-to-CSS) - the cheapest path, done incrementally, the GTK 4 after the 3.
  • The new app starts on the active stack for its target. The native GNOME is the PyGObject/GTK (the 4 for the current, the 3 for the broader), the cross-platform is the Qt or the web-based, the no-dependency utility is the Tkinter - the start is the unconstrained decision.
  • The team's familiarity is a real cost. The GTK team stays on the GTK line, the Qt team on the Qt, the web team on the web - the learning cost is weighed against the ecosystem gain, not ignored.
  • The stable legacy app stays until the targets force the move. The maintenance PyGTK on the GTK 2 targets is acceptable, and the migration is the project the target change triggers, not the one started before the need - the stability of the running app is a value the migration must beat.

Summary

The choice between PyGTK and the modern stack is the support horizon and the ecosystem, not the features. The options and their status: PyGTK (the maintenance binding, the GTK 2 libraries leaving the distros), PyGObject on GTK 3 (the stable successor, the same architecture), PyGObject on GTK 4 (the active current, the changed render model), the Tkinter (the standard-library, the basic, the no-dependency), the PyQt/PySide (the commercial-grade cross-platform), and the web-based (the HTML/CSS in a native window). The criteria are the four, weighted: the support horizon (the targets' libraries over the app's life), the ecosystem (the theming, the integration, the widget set), the existing code (the PyGTK app's cheapest path is the PyGObject migration, the architecture carrying), and the team (the familiarity cost). The recommendation by case: the maintained PyGTK app migrates to PyGObject/GTK 3 (the GTK 4 after, when the features need it), the new native app starts on the PyGObject/GTK, the new cross-platform app is the Qt or the web-based, the no-dependency utility is the Tkinter, and the stable legacy app stays on PyGTK until the targets force the move. The through-line: the GTK architecture learned on PyGTK is the architecture of the modern stack, and the binding change is the spelling.