Search code examples
python-3.xbuttongtktoolbarpygobject

Make a specific button in PyGObject as small as possible


I would like to have a toolbar button with a label but without an icon that is as small as possible. There is no need for margins between the text on the button and the border of the button. It has not to be a real toolbar. It can also be a simple horizontal line of buttons.

#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk


class MyWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect('destroy', Gtk.main_quit)

        # try it as a toolbar
        toolbar = Gtk.Toolbar()
        for i in range(3):
            widget = Gtk.Label(str(i), expand=False)
            #widget.set_margin_start(0)
            btn = Gtk.ToolButton.new()
            btn.set_label_widget(widget)
            toolbar.insert(btn, -1)

        # try it as simple button line
        hbox = Gtk.HBox()
        for i in range(5):
            btn = Gtk.Button(label=str(i), expand=False, relief=2)
            hbox.pack_start(btn, expand=False, fill=False, padding=0)

        # layout
        vbox = Gtk.VBox()
        vbox.pack_start(toolbar, expand=False, fill=False, padding=0)
        vbox.pack_start(hbox, expand=False, fill=False, padding=0)
        self.add(vbox)


if __name__ == '__main__':
    window = MyWindow()
    window.show_all()
    Gtk.main()

EDIT: Not all buttons in the application should be like this. I need this specific "style" only for some of them.


Solution

  • Overriding some CSS properties should do the trick. Here's a quick modification of your script.

    #!/usr/bin/env python3
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk
    
    # Added code starts here
    from gi.repository import Gdk
    
    css = b"""
    .small-button {
      min-height: 0px;
      padding-bottom: 0px;
      padding-top: 0px;
    }
    """
    
    css_provider = Gtk.CssProvider()
    css_provider.load_from_data(css)
    
    Gtk.StyleContext.add_provider_for_screen(
        Gdk.Screen.get_default(),
        css_provider,
        Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
    )
    # End of added code
    
    class MyWindow(Gtk.Window):
        def __init__(self):
            Gtk.Window.__init__(self)
            self.connect('destroy', Gtk.main_quit)
    
            # try it as a toolbar
            toolbar = Gtk.Toolbar()
            for i in range(3):
                widget = Gtk.Label(str(i), expand=False)
                #widget.set_margin_start(0)
                btn = Gtk.ToolButton.new()
                btn.set_label_widget(widget)
                toolbar.insert(btn, -1)
    
            # try it as simple button line
            hbox = Gtk.HBox()
            for i in range(5):
                btn = Gtk.Button(label=str(i), expand=False, relief=2)
                style_ctx = btn.get_style_context()
                style_ctx.add_class('small-button')
                hbox.pack_start(btn, expand=False, fill=False, padding=0)
    
            # layout
            vbox = Gtk.VBox()
            vbox.pack_start(toolbar, expand=False, fill=False, padding=0)
            vbox.pack_start(hbox, expand=False, fill=False, padding=0)
            self.add(vbox)
    
    
    if __name__ == '__main__':
        window = MyWindow()
        window.show_all()
        Gtk.main()
    

    Changing the CSS of just a specific set of widgets can be done by appointing a new class to them. First get the GtkStyleContext of those widgets and then use its add_class('class-name') method:

    style_ctx = button.get_style_context()
    style_ctx.add_class('small-button')
    

    See the theming section in the GTK documentation for more information about CSS theming.

    Run your GUI with the GtkInspector to inspect the widget's CSS properties.