Search code examples
pythonbuttongtk3

Gtk3 Button - Reduce Padding of Internal Label


I have a Gtk.Button, and I would like to reduce the internal left and right padding inside the button, so the button's label is shown with smaller margins on the left and right sides.

I am able to increase the margins using...

label = button.get_child()
label.set_margin_start(50)
label.set_margin_end(50)

But I am unable to reduce the margins. Setting the margins to zero has no effect...

label = button.get_child()
label.set_margin_start(0)
label.set_margin_end(0)

I also tried getting the style context, and reading the margin properties...

label = button.get_child()
style_context = label.get_style_context()
margin = style_context.get_margin(Gtk.StateFlags.NORMAL)
print('left   = %s' % margin.left)
print('right  = %s' % margin.right)   
print('top    = %s' % margin.top)   
print('bottom = %s' % margin.bottom)

But it is already zero for all sides...

left   = 0
right  = 0
top    = 0
bottom = 0

How could I reduce the left and right padding of the text inside the button?

EDIT: I've added test code below.


basic_window.py

#!/usr/bin/python3

import gi

gi.require_version('Gtk', '3.0')
from gi.repository import GLib
from gi.repository import Gtk

class MainWindowHandlers(Gtk.Window):

    def on_window_destroy(self, *args):

        print('Exit')
        GLib.idle_add(Gtk.main_quit)

    def on_clicked_button_1(self, button):

        print('----------------------------------')
        print('Button 1 Clicked')
        print('----------------------------------')

        # Get the child label.
        label = button.get_child()

        # Set the child's margins to 30. They expand.
        label.set_margin_start(20)
        label.set_margin_end(20)

        # Investigate the child's style context.
        style_context = label.get_style_context()
        margin = style_context.get_margin(Gtk.StateFlags.NORMAL)
        print('left   = %s' % margin.left)
        print('right  = %s' % margin.right)   
        print('top    = %s' % margin.top)   
        print('bottom = %s' % margin.bottom)

        print('----------------------------------')
        print()

    def on_clicked_button_2(self, button):

        print('----------------------------------')
        print('Button 2 Clicked')
        print('----------------------------------')

        # Get the child label.
        label = button.get_child()

        # Set the child's margins to 0.
        # They stay the same size.
        # This does not reduce the left/right padding as I expect.
        label.set_margin_start(0)
        label.set_margin_end(0)

        # Investigate the child's style context.
        style_context = label.get_style_context()
        margin = style_context.get_margin(Gtk.StateFlags.NORMAL)
        print('left   = %s' % margin.left)
        print('right  = %s' % margin.right)   
        print('top    = %s' % margin.top)   
        print('bottom = %s' % margin.bottom)

        print('----------------------------------')
        print()

try:

    builder = Gtk.Builder.new_from_file('basic_window.ui')

    handlers = MainWindowHandlers()
    builder.connect_signals(handlers)

    window = builder.get_object('window')
    window.show()

    Gtk.main()

except Exception as exception:

    print('Error: %s' % exception)

basic_window.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window">
    <property name="can_focus">False</property>
    <property name="default_width">500</property>
    <property name="default_height">300</property>
    <signal name="destroy" handler="on_window_destroy" swapped="no"/>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkGrid">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkButton" id="button_2">
            <property name="label" translatable="yes">Add 20 Pixels</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="halign">center</property>
            <property name="valign">center</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <signal name="clicked" handler="on_clicked_button_1" swapped="no"/>
            <style>
              <class name="suggested-action"/>
            </style>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="button_1">
            <property name="label" translatable="yes">Set to 0 Pixels</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="halign">center</property>
            <property name="valign">center</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <signal name="clicked" handler="on_clicked_button_2" swapped="no"/>
            <style>
              <class name="suggested-action"/>
            </style>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Solution

  • I reduced margin using style {padding: 0}

    But if there is other button with bigger margin/padding then (in my example) Box() resizes first button to use the same sizes. It may need different layout manager

    import gi
    gi.require_version("Gtk", "3.0")
    from gi.repository import Gtk
    from gi.repository import Gdk
    
    
    class ButtonWindow(Gtk.Window):
        def __init__(self):
            Gtk.Window.__init__(self)
    
            screen = Gdk.Screen.get_default()
            provider = Gtk.CssProvider()
            style_context = Gtk.StyleContext()
            style_context.add_provider_for_screen(screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
            #provider.load_from_path('app.css')
            #provider.load_from_data("#small {margin: 0; padding: 0;}".encode())
            provider.load_from_data("#small {padding: 0;}".encode())
    
            hbox = Gtk.Box()
            self.add(hbox)
    
            button1 = Gtk.Button.new_with_label("Padding 0")
            button1.set_name('small') # assign CSS with padding 0
            hbox.pack_start(button1, False, False, 0)
    
            #button2 = Gtk.Button.new_with_label("Normal padding")
            #hbox.pack_start(button2, True, True, 0)
    
            #button2.set_name('small') # assign CSS with padding 0
    
    win = ButtonWindow()
    win.connect("destroy", Gtk.main_quit)
    win.show_all()
    Gtk.main()
    

    {padding: 0}

    enter image description here

    Second button (with standard padding) is higher and automatically it adds top/bottom padding to first button.

    enter image description here

    Both buttons with {padding: 0}

    enter image description here