#!/usr/bin/env python3 import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gdk, GdkPixbuf import os import textwrap # Return a pixbuf from icon name def get_icon(name, size): """ Return a GdkPixbuf.Pixbuf """ found = False if name.startswith('/'): try: # name is an absolute pathname to a file pixbuf = GdkPixbuf.Pixbuf.new_from_file(name) pixbuf = pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.BILINEAR) found = True except gi.repository.GLib.GError: name = os.path.basename(name).split('.')[0] if not found: theme = Gtk.IconTheme.get_default() try: pixbuf = theme.load_icon(name, size, Gtk.IconLookupFlags.USE_BUILTIN) except gi.repository.GLib.GError: try: filename = os.path.join('/usr/share/pixmaps', name) pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename) found = True except gi.repository.GLib.GError: pixbuf = theme.load_icon(Gtk.STOCK_PREFERENCES, 16, 0) if pixbuf.get_width() != size or pixbuf.get_height() != size: pixbuf = pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.BILINEAR) return pixbuf # My widget: icon and label wrapped in an EventBox class DesktopToolWidget(Gtk.EventBox): def __init__(self, label, icon_name, icon_size=48, orientation=Gtk.Orientation.VERTICAL, border=4, wrap=0): Gtk.EventBox.__init__(self) self.set_border_width(0) self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK) vbox = Gtk.Box(orientation=orientation, spacing=border) vbox.set_border_width(int(border / 2)) btn_image = Gtk.Image() pixbuf = get_icon(icon_name, icon_size) btn_image.set_from_pixbuf(pixbuf) vbox.pack_start(btn_image, expand=False, fill=False, padding=0) if label is not None: label_markup = textwrap.fill(label, wrap) if wrap else label btn_label = Gtk.Label(label_markup, wrap=True) btn_label.set_use_markup(True) vbox.pack_start(btn_label, expand=False, fill=False, padding=0) self.add(vbox) self.show_all() def connect_clicked(self, callback, *args): self.connect("button_press_event", lambda widget, event: callback(*args)) class Test: Value = 5 def do_something(self, args): print("do_something: args:", args, "value:", self.Value) class MainWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="DesktopToolWidget Test") self.set_border_width(10) vbox = Gtk.VBox(spacing=8) icon_size = 48 # Button 1 icon_button1 = DesktopToolWidget("Hello\nIconButton", 'vlc', icon_size) icon_button1.set_size_request(150, 150) vbox.pack_start(icon_button1, expand=False, fill=False, padding=0) # Attach a callback test = Test() icon_button1.connect_clicked(test.do_something, "Hello") # Button 2 label = "Hello\nIconButton Horizontal" icon_button2 = DesktopToolWidget(label, 'synaptic', icon_size, Gtk.Orientation.HORIZONTAL) icon_button2.set_size_request(200, 100) vbox.pack_start(icon_button2, expand=False, fill=False, padding=0) # Button 3 label = "HelloThis is a very long label a very long label a very long label" icon_button3 = DesktopToolWidget(label, 'synaptic', icon_size, Gtk.Orientation.HORIZONTAL, wrap=30) icon_button3.set_size_request(200, 100) vbox.pack_start(icon_button3, expand=False, fill=False, padding=0) self.add(vbox) if __name__ == "__main__": win = MainWindow() win.connect("destroy", Gtk.main_quit) win.show_all() Gtk.main()