First: the method gtk.Window.resize() doesnt't work with a single argument (setting the other to -1, as instead does gtk.Widget.set_size_request()). OK, this is documented, though ugly.
Now: if a gtk.Window w has size (100,100) and we run the following code:
w.resize(200,200) size = w.get_size() w.resize(*size)
, then the window won't resize to 200,200, but to 100,100. In fact “resize” doesn't really resize, it just queues a resize process, while if we use get_size we get the current size, not the queued one. This means if several functions try to resize (and it makes sense, if each one takes care of a single dimension), we have race conditions.
I solved that (both problems) with the following functions:
def unset_real_size(window, event):
"""Fields 'real width' and 'real height' become obsolete (or at least
useless) when a resize actually takes place.
"""
window.set_data('real width', None)
window.set_data('real height', None)
handler = window.get_data('configure handler')
if handler:
# The callback is now useless; remove it.
window.disconnect(handler)
window.set_data('configure handler', None)
def ensure_configure_handler(window):
"""Ensure that unset_real_size is called.
"""
if not window.get_data('configure handler'):
new_handler = window.connect('configure-event', unset_real_size)
window.set_data('configure handler', new_handler)
def get_width(window):
width = window.get_data('real width')
if not width:
width = window.get_size()[0]
return width
def get_height(window):
height = window.get_data('real height')
if not height:
height = window.get_size()[1]
return height
def set_width(window, width):
ensure_configure_handler(window)
window.set_data('real width', width)
height = get_height(window)
window.resize(width, height)
def set_height(window, height):
ensure_configure_handler(window)
window.set_data('real height', height)
width = get_width(window)
window.resize(width, height)
Notice that set_size_request has a similar problem: if a gtk.Widget widget's get_size_request gives (-1,-1) and I run the following code:
widget.set_size_request(100,100) widget.set_size_request(-1, -1)
, it won't expand at all, nothing will happen. This is an issue if you wanted to use this as a hack to resize the widget but let to the user the possibility to shrink it again; an hackish way to solve this is instead the following code:
widget.set_size_request(100,100) gobject.idle_add(widget.set_size_request, -1, -1)
While gtk.Containers usually propagate size requests from child(ren) to parent, gtk.ScrolledWindow doesn't; instead, it sets a predefined (hardcoded, presumably) size. Apparently, this makes sense: if you want the whole widget shown, why a ScrolledWindow?! However, there are 2 situations in which this is hateful:
I solved this with the following code (widget is the widget we want to resize so that it is fully shown), thanks to owen in freenode.irc's #gtk+ for the hint:
scrolledwindows = []
scrolledwindows_policies = []
scrolledwindows_hscrollbars = []
while widget:
# The ScrolledWindows stop propagation of queue_redraws, unless they
# have the scrollbars disabled, so here we disable them...
if gobject.type_is_a(widget, gtk.ScrolledWindow):
scrolledwindows.append(widget)
scrolledwindows_policies.append(widget.get_policy())
widget.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)
scrolledwindows_hscrollbars.append(widget.get_hscrollbar())
widget = widget.get_parent()
toplevel = treeview.get_toplevel()
# ... then we can take the size...
new_width = toplevel.size_request()[0]
# ... add the size of bars...
bars_width = 0
for index in range(len(scrolledwindows)):
# (not needed if the policy hides it)
if scrolledwindows_policies[index][0] == gtk.POLICY_ALWAYS:
bars_width += scrolledwindows_hscrollbars[index].size_request()[0]
scrolledwindows[index].set_policy(*scrolledwindows_policies[index])
# print "width:", new_width
# ... and put together the total size.
new_width += bars_width