Search code examples
pythonwidgetgtkgtk3

How to set minimum/preferred size in custom Gtk widget


I'm trying to implement a custom Gtk widget, but I can't figure out how to request a specific minimum size and preferred size.

Here you can see that I (try to) request a minimum size of 300x300 and preferred size of 500x500, but Gtk never even calls any of those functions and creates a 200x200 window:

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


class MyWidget(Gtk.DrawingArea):
    # None of these are ever called
    def do_get_preferred_width_for_height(self, height):
        print('do_get_preferred_width_for_height')
        return 300, 500
    
    def do_get_preferred_height_for_width(self, width):
        print('do_get_preferred_height_for_width')
        return 300, 500

    def do_get_preferred_size(self):
        print('do_get_preferred_size')
        min_size = Gtk.Requisition()
        min_size.width = min_size.height = 300

        pref_size = Gtk.Requisition()
        pref_size.width = pref_size.height = 500

        return min_size, pref_size
    
    def do_size_request(self, requisition):
        print('do_size_request')
        requisition.width = 500
        requisition.height = 500
    
    # Except for these two
    def do_get_request_mode(self):
        print('do_get_request_mode')
        return Gtk.SizeRequestMode.CONSTANT_SIZE
    
    def do_draw(self, context):
        print('Window size:', window.get_allocated_width(), window.get_allocated_height())
        width = self.get_allocated_width()
        height = self.get_allocated_height()
        
        context.set_source_rgb(0, 1, 0)
        context.rectangle(0, 0, width, height)
        context.fill()

window = Gtk.Window()
window.add(MyWidget())
window.show_all()
window.connect('destroy', Gtk.main_quit)
Gtk.main()

# Output:
# do_get_request_mode
# do_get_request_mode
# Window size: 200 200

What am I doing wrong?


Solution

  • The problem here (see this comment by the OP) is that the do_get_preferred_height() and do_get_preferred_width() methods are not implemented. Here is the code you need to add to your class:

    def do_get_preferred_height(self):
        print('get_preffered_height') # So you can see when it's called
        return 300, 500
    
    def do_get_preferred_width(self):
        print('get_preffered_width') # So you can see when it's called
        return 300, 500
    

    This should make the window have an initial size of 500x500, and a minimum size of 300x300.