How to build an app with Python and GTK on ChromeOS

Renato CruzRenato Cruz
4 min read

To prepare a Chromebook development environment for creating applications using Python (PyGObject) and the GTK graphical toolkit, follow these steps.

Note: The Linux environment must be configured on ChromeOS beforehand. Additional configurations may be necessary depending on the Debian version.

Debian Bookworm

Debian Bookworm includes GTK 4 packages in its stable repositories. Open the terminal and execute the following command:

sudo apt -t sid install \
python3-full \
python3-dev \
python3-gi \
python3-gi-cairo \
libcairo2-dev \
libgirepository1.0-dev \
gir1.2-gtk-4.0 \
libgtk-4-dev \
libadwaita-1-dev

Once the installation is complete, Python, PyGObject binding, and GTK graphics libraries will be installed on ChromeOS.

Debian Buster and Bullseye

For Debian Buster and Bullseye, GTK 4 packages are not available in stable repositories, requiring the configuration of the sid repository.

Debian Sid

To add the sid repository, edit the sources.list file. Open the terminal and install nano if you are not familiar with vi or vim:

sudo apt install nano

After installation, type the following in the terminal:

sudo nano /etc/apt/sources.list

Now, add the testing (sid) repository to the sources.list file:

# Generated by distrobuilder
deb https://deb.debian.org/debian bullseye main
deb https://deb.debian.org/debian bullseye-updates main
deb https://deb.debian.org/debian-security/ bullseye-security main

deb http://http.us.debian.org/debian sid main non-free contrib

Warning: Do not run sudo apt update or sudo apt upgrade!

Next, create or edit the preferences file. If this configuration is not done, the system will attempt to update all packages, potentially leading to broken packages. In the terminal, execute:

sudo nano /etc/apt/preferences

Inside this file, add the following code:

Package: *
Pin: release a=stable
Pin-Priority: 700

Package: *
Pin: release a=testing
Pin-Priority: 650

Package: *
Pin: release a=unstable
Pin-Priority: 600

Save the file, then update the repositories:

sudo apt update

After the repository update is finished, run the following command to install the necessary packages:

sudo apt -t sid install \
python3-full \
python3-dev \
python3-gi \
python3-gi-cairo \
libcairo2-dev \
libgirepository1.0-dev \
gir1.2-gtk-4.0 \
libgtk-4-dev \
libadwaita-1-dev

After installation, Python, GTK 4 toolkit, and PyGObject binding will be ready for use on ChromeOS.

Virtual Environments

Consider using virtual environments for project isolation. Some popular options include:

  • Poetry

  • Pipenv

  • Pyenv

  • PDM

  • venv (native)

Creating a Virtual Environment

Navigate to your project's root folder, open a terminal, and execute:

python3 -m venv venv

To create a virtual environment with a specific Python version, use:

python3.X -m venv venv

Note: Replace X with the desired Python version, and ensure the version is installed on your operating system.

Activating the Virtual Environment

After creation, the virtual environment must be activated; otherwise, packages will be installed in the system's local Python installation. To activate:

source venv/bin/activate

Installing the Binding

With the virtual environment active, first upgrade pip:

python -m pip install \
--upgrade pip

Then, install the PyGObject binding and PyGObject-stubs library:

pip install \
pygobject \
PyGObject-stubs

This sets up an isolated environment for development.

Testing

The simplest way to test communication between Python and GTK is by running the following command in the terminal:

python3 -c "import gi"

Note: This command must be executed with the virtual environment active! If no errors are returned, the Python and GTK environment setup on your Chromebook is correct.

Example Code

Use the following example code in your text editor or IDE to test the configuration:

# -*- coding: utf-8 -*-
"""Python e GTK: PyGObject Gtk.ApplicationWindow()."""

import gi

gi.require_version(namespace='Gtk', version='4.0')
gi.require_version(namespace='Adw', version='1')

from gi.repository import Adw, Gio, Gtk

Adw.init()


class ExampleWindow(Gtk.ApplicationWindow):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.set_title(title='Python - PyGObjet - GTK:')
        self.set_default_size(width=int(1366 / 2), height=int(768 / 2))
        self.set_size_request(width=int(1366 / 2), height=int(768 / 2))

        headerbar = Gtk.HeaderBar.new()
        self.set_titlebar(titlebar=headerbar)

        menu_button_model = Gio.Menu()
        menu_button_model.append('Preferências', 'app.preferences')

        menu_button = Gtk.MenuButton.new()
        menu_button.set_icon_name(icon_name='open-menu-symbolic')
        menu_button.set_menu_model(menu_model=menu_button_model)
        headerbar.pack_end(child=menu_button)

        # Your code here:
        # ...


class ExampleApplication(Adw.Application):

    def __init__(self):
        super().__init__(application_id='br.com.justcode.Example',
                         flags=Gio.ApplicationFlags.FLAGS_NONE)

        self.create_action('quit', self.exit_app, ['<primary>q'])
        self.create_action('preferences', self.on_preferences_action)

    def do_activate(self):
        win = self.props.active_window
        if not win:
            win = ExampleWindow(application=self)
        win.present()

    def do_startup(self):
        Gtk.Application.do_startup(self)

    def do_shutdown(self):
        Gtk.Application.do_shutdown(self)

    def on_preferences_action(self, action, param):
        print('Ação app.preferences foi ativa.')

    def exit_app(self, action, param):
        self.quit()

    def create_action(self, name, callback, shortcuts=None):
        action = Gio.SimpleAction.new(name, None)
        action.connect('activate', callback)
        self.add_action(action)
        if shortcuts:
            self.set_accels_for_action(f'app.{name}', shortcuts)


if __name__ == '__main__':
    import sys

    app = ExampleApplication()
    app.run(sys.argv)
0
Subscribe to my newsletter

Read articles from Renato Cruz directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Renato Cruz
Renato Cruz