Stephen Langer wrote: > 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 > width. > > 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 > two. > > 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. > > Thanks, > Steve > > > > import gtk > > def setPos(pane, signal, pos): > "Set a Paned position without propagating signals" > pane.handler_block(signal) > pane.set_position(pos) > pane.handler_unblock(signal) > > 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) > else: > 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) > else: > print "bottom" > setPos(topPane, topSignal, pos) > elif count > 1: > count = 0 > > window = gtk.Window() > box = gtk.VBox() > window.add(box) > 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) > > window.show_all() > > gtk.main() > > You have to allow the widgets to shrink - remove the "shrink=0" args from the pack1() and pack2() calls.
John _______________________________________________ pygtk mailing list pygtk@daa.com.au http://www.daa.com.au/mailman/listinfo/pygtk Read the PyGTK FAQ: http://faq.pygtk.org/