There may be times you have a simple choice or listing in a GTK list box – for this example, in choosing a serial connection or other device. Glade is a good way to build an application window easily with an interface to build in to your app on Linux desktop, Ubuntu or Librem phone or other Linux based phones. I was able to use this to create a Winlink user interface for the previous tutorial to call up the Pat interface.
The first thing we will need is a window, starting out a new file:
Next, add a container into this Gtkwindow – Note the three segments that will be filled in with controls:
Within the GTKBox, add the controls. The right panel will let you change attributes such as the ID (the name you use to reference the control in the code), and various control visibility settings, in the right panel.
Later when you want to add more buttons or spacers you can select the + button in the right properties box while selecting the GtkBox on the left panel.
Python code running the application and logic
Now we need the code to call up the dialog along with its button functions. When you look up examples to get started, make sure you are looking at GTK3 code and not old “PyGTK” tutorials. This one for example is a good reference for the GTK3 and Python3. The installation instructions should not be necessary on Linux systems on which you can install package “python3-gi”.
To get this working with your code you will need to connect “signals” to methods within a class that controls the window, use builder.connect_signals(class) for the builder instance you use calling up this .glade file when the file is initialized – like so:
import os import sys import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import GObject from gi.repository import GLib from gi.repository import Pango import json from pandas import read_json class Listing: def __init__(self): pass def show(self): #Create GtkDialog self.builder = Gtk.Builder() self.builder.add_from_file('Listing.glade') self.builder.connect_signals(self) self.dialog = self.builder.get_object('MainDialog') self.dialog.set_default_size(300,300) self.dialog.show_all() def refresh(self, btn): print(btn) def go(self, btn): print('go button clicked') if __name__ == '__main__': dlg = Listing(); dlg.show() Gtk.main()
Now the Listing() class is created, show is called bringing up a dialog, and the “refresh” and “go” are connected to signals selected in the right most panel properties of the button:
You can make a button a “stock” icon button by setting the option in the General panel:
Handling a list
A common control in any application is a list chooser, and the GtkListBox, which can be changed programmatically: Note the clearing removes each child (.get_children()):
#!/usr/bin/env python # -*- coding: utf-8 -*- # # A Winlink User interface import os import sys import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import GObject from gi.repository import GLib from gi.repository import Pango import json from pandas import read_json class Listing: def __init__(self): pass def show(self): """ Create GtkDialog """ self.builder = Gtk.Builder() self.builder.add_from_file('Listing.glade') self.builder.connect_signals(self) self.dialog = self.builder.get_object('MainDialog') self.dialog.set_default_size(300,300) self.refresh(None) self.dialog.show_all() def refresh(self, btn): """ Refresh """ listbox = self.builder.get_object('list') for row in listbox.get_children(): listbox.remove(row) if os.path.exists('/dev/serial/by-id'): for entry in os.scandir('/dev/serial/by-id'): if not entry.name.startswith('.') and not entry.is_dir(): path = os.path.normpath(os.path.join(os.path.dirname(entry.path), os.readlink(entry.path))) print(path) self.addEntry(entry.name, path) else: self.addEntry("No serial devices detected.","") listbox.show_all() def addEntry(self, label, path): listbox = self.builder.get_object('list') row = Gtk.ListBoxRow() hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0) lbl = Gtk.Label(label=label) lbl.set_ellipsize(Pango.EllipsizeMode.END) hbox.pack_start( lbl, True, True, 2 ) row.path = path row.add(hbox) listbox.add(row) def go(self, btn): """ Go button connects, opens browser Pat interface. """ gtklist = self.builder.get_object('list') path = gtklist.get_selected_row().path os.system('gksudo kissattach '+path+' wl2k') os.system("xdg-open 'http://localhost:8080'") os.system('pat http') def stop(self, btn): """ Stop and quit """ Gtk.main_quit() exit; if __name__ == '__main__': dlg = Listing(); dlg.show() Gtk.main()
This lets one call up Pat for a Mobilinkd device with a radio. Check out the full code in the Github Repo!
2 Replies to “GTK Choice box with Glade and Python”
Nice, thanks 🙂 Would you know how to pop open the same menu (or any Glade-defined menu) on a right-click anywhere in the window ?
Here you can see an example of creating a right click menu upon mouse-button-press: https://github.com/programmin1/Repeater-START/commit/80ae5125a07be4dbcee373094d19547fd6c490d3