Search code examples
pythonpygtkscrolledwindow

Prevent scrollbars from showing up when placing a drawing area inside a scrolled window


I'm working on a project using Python and pyGTK. I have a window whose only purpose is showing an image. Unless the image is too big to fit the screen, the window should show no scrollbars by default.
So what I do is something like this:

window = gtk.Window()
window.resize(image.size[0], image.size[1])

scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_NONE)

area = gtk.DrawingArea()
area.set_size_request(image.size[0], image.size[1])

window.add(scrolled)
scrolled.add_with_viewport(area)
area.show()
scrolled.show()
window.show()

But it doesn't quite work. The resulting window is a little too small, and thus, scrollbars show up.
For it to work, I have to thange the second line to this:

window.resize(image.size[0] + 2, image.size[1] + 2)

But that is ugly, and it doesn't work under all systems. In my Windows box I have to use + 3.

What can I do to make sure the window is big enough for the image?


Solution

  • I figured it out :).

    If you put a DrawingArea inside a ScrolledWindow, things just won't work as they should. Instead, you have to put the DrawingArea in a Viewport, and the Viewport in the ScrolledWindow. gtk.ScrolledWindow provides a method, gtk.ScrolledWindow.add_with_viewport, that does this automatically, for convenience's sake. The problem is the viewport generated by that method has a border by default, and that border varies in width depending on the system. Also, there's no way (that I know of) of accessing the generated Viewport (edit: you can use scrolled.get_child()) to get rid of the border. The solution is simple: you have to manually create the Viewport.

    window = gtk.Window()
    window.resize(image.size[0], image.size[1])
    
    scrolled = gtk.ScrolledWindow()
    scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
    scrolled.set_shadow_type(gtk.SHADOW_NONE)
    
    viewport = gtk.Viewport()
    viewport.set_shadow_type(gtk.SHADOW_NONE)  // Get rid of the border.
    
    area = gtk.DrawingArea()
    area.set_size_request(image.size[0], image.size[1])
    
    window.add(scrolled)
    scrolled.add(viewport)
    viewport.add(area)
    viewport.show()
    area.show()
    scrolled.show()
    window.show()
    

    It worked like a charm on Arch (GNOME 3), Windows XP, Windows 7 and Ubuntu (Unity).