How to build an app with Python and GTK on ChromeOS
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:
After installation, type the following in the terminal:
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:
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:
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:
To create a virtual environment with a specific Python version, use:
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:
Installing the Binding
With the virtual environment active, first upgrade pip:
Then, install the PyGObject binding and PyGObject-stubs library:
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:
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)