[pygtk] synchronizing HPaned widgets

Stephen Langer stephen.langer at nist.gov
Fri Feb 6 03:19:12 WST 2009

Hi --

I'm hoping that someone can tell me if this is a bug or if I'm doing  
something wrong.

I have two HPaned widgets whose separators I'd like to keep  
synchronized.  Both Paneds are in the same VBox, so they have the same  

As described at http://faq.pygtk.org/index.py?req=show&file=faq19.013.htp 
, I connect to the 'notify' signal for each pane to find out when the  
separator has been moved.  The callback function blocks the signal for  
the other  pane, changes its position to match the first pane, and  
then unblocks the signal.

The problem is that the signal doesn't seem to be blocked sometimes,  
so the program goes into an infinite loop.  There are easy workarounds  
for this, but they're ugly and unsatisfying.  In particular, the  
program loops when the panes are first shown if the contents of two  
diagonally opposite subpanes are larger than the contents of the other  

I've appended short program that illustrates the problem.  Just  
starting the program will put it into an infinite loop.  If you  
replace paneMoved by paneMoved_workaround, the problem goes away.

Why doesn't blocking the signal work?  Am I doing something wrong?

I've run this test on OS X with python 2.5, gtk 2.14.7, and pygtk  
2.12.1, and on Linux with python 2.4, gtk 2.8.20, and pygtk 2.8.6.


import gtk

def setPos(pane, signal, pos):
     "Set a Paned position without propagating signals"

def paneMoved(pane, gparamspec):
     "Callback for synchronizing Paned position changes"
     if gparamspec.name == 'position':
         pos = pane.get_position()
         if pane is topPane:
             print "top"
             setPos(botPane, botSignal, pos)
             print "bottom"
             setPos(topPane, topSignal, pos)

count = 0
def paneMoved_workaround(pane, gparamspec):
     "Callback for synchronizing Paned position changes"
     global count
     if gparamspec.name == 'position':
         count += 1
         pos = pane.get_position()
         if count == 1:
             if pane is topPane:
                 print "top"
                 setPos(botPane, botSignal, pos)
                 print "bottom"
                 setPos(topPane, topSignal, pos)
         elif count > 1:
             count = 0

window = gtk.Window()
box = gtk.VBox()
window.connect("delete-event", gtk.main_quit)

# Create two panes, one on top of the other
topPane = gtk.HPaned()
box.pack_start(topPane, expand=1, fill=1)
botPane = gtk.HPaned()
box.pack_start(botPane, expand=1, fill=1)

# Synchronize the pane positions
topSignal = topPane.connect('notify', paneMoved)
botSignal = botPane.connect('notify', paneMoved)

# If the displayed sizes of shortstring and longstring are different,
# the program will enter an infinite loop after show_all().  If the
# strings are identical, the program behaves correctly (no infinite
# loop, the panes can be resized and stay synchronized).
shortstring = "string"
longstring = "long string"      # Try "String" too.

# Put each string into two diagonally opposite labels in the panes.
topPane.pack1(gtk.Label(longstring), resize=1, shrink=0)
topPane.pack2(gtk.Label(shortstring), resize=1, shrink=0)

botPane.pack1(gtk.Label(shortstring), resize=1, shrink=0)
botPane.pack2(gtk.Label(longstring), resize=1, shrink=0)



-- EMail: stephen.langer at nist.gov                    Phone: (301)  
975-5423 --
-- WWW:  http://math.nist.gov/mcsd/Staff/SLanger/    Fax:   (301)  
975-3553 --
-- Mail: NIST; 100 Bureau Drive -- Stop 8910; Gaithersburg, Md   
20899-8910 --

-- "I don't think this will work.  That's why it's  
science."               --
--                              Naomi Langer (age 6),  17 Feb  
2003         --

More information about the pygtk mailing list