From: Fernando P. <Fer...@co...> - 2006-01-21 23:19:41
|
In [1]: gcf().set_figsize_inches((8,8),forward=True) --------------------------------------------------------------------------- exceptions.TypeError Traceback (most recent call last) /home/fperez/code/python/pylab/arrows/<ipython console> /usr/lib/python2.3/site-packages/matplotlib/figure.py in set_figsize_inches(self, *args, **kwargs) 266 canvasw = w*dpival 267 canvash = h*dpival --> 268 self.canvas.resize(int(canvasw), int(canvash)) 269 270 def get_size_inches(self): TypeError: resize() takes exactly 2 arguments (3 given) A quick look at the backends code shows this: def resize(self, event): width, height = event.width, event.height self.toolbar.configure(width=width) # , height=height) So quite obviously, this doesn't work: it's expecting an event object, and a pair of numbers is being passed. I'm not sure what the proper fix should be here, I don't really know the code flow well enough. I should also note that the gcf().set_figsize_inches((8,8),forward=True) seems to produce a different on-screen result per backend (in some it doesn't do anything, in Qt it stretches the figure only horizontally, ...) That code seems to be pretty much broken. I noticed that figure(figsize=(8,8)) seems to work fine, but I'm not sure how to programmatically resize an existing figure, given the above problems. Cheers, f |
From: John H. <jdh...@ac...> - 2006-01-22 18:35:25
|
>>>>> "Fernando" == Fernando Perez <Fer...@co...> writes: Fernando> TypeError: resize() takes exactly 2 arguments (3 given) Yes, this is basically broken on all GUIs except GTK*. There was a fair amount of discussion back in octover on the devel list about how to do this right, since basically it requires a child to call a method on the parent and we don't know a-priori what the container will be. In pylab we can make it work (but haven't yet across backends) because we know the parent will be a FigureManager instance, but it would be nice to come up with a generic method that works regardless of whether you are using mpl in pylab or not. It's on the slow burner, currently. JDH |
From: Ted D. <ted...@jp...> - 2006-01-23 16:51:26
|
John & Fernando, I think the basic problem can be solved in a number of ways. Normally a GUI widget will have an initial size and when it is placed in a window, the window will layout around it (or to it's own size). However, once the window is drawn, changing the size of one or more widget that it contains doesn't mean you're changing the size of the window. Here's some ideas for how to fix this: 1) Tell people they have to use the resize method on the window object. Pro: simple. Con: not really the API that you want. 2) Write a resize method (but probably don't call it 'resize' because every widget system already uses that name) and have it emit a signal (callback). When you construct the window object, connect that signal to a resize method (again not called 'resize') on the window object that can compute it's correct size based on the new plot size. This way the plot doesn't know who's getting the signal and can remain independent of it's container. 3) Explore the different backends and see if there is a way to configure the window objects so they dynamically resize when a child widget is changed. I did a quick check through Qt and couldn't find anything for this but it might be there. It seems like 2) would be pretty simple to implement. In the Qt backend, I think you could do this by: backend_qtagg.py: In FigureCanvasQTAgg.resizeEvent, add an emit call to create a new signal. self.emit( qt.PYSIGNAL( "plotResize" ), ( w, h ) ) backend_qt.py: In FigureManagerQT.__init__, connect that signal to a new method resizeFromPlot( w, h ). This method should contain the code from the current __init__ method that resizes the window based on a given plot size. self.connect( self.canvas, PYSIGNAL( "plotResize" ), self.resizeFromPlot ) This should make it so that any size change to the plot will trigger a resize on the main window. There may be a circularity problem but we'd have to try it first an see if calling resize on the main window triggers a resize in the plot. Ted At 10:25 AM 1/22/2006, John Hunter wrote: > >>>>> "Fernando" == Fernando Perez <Fer...@co...> writes: > > > Fernando> TypeError: resize() takes exactly 2 arguments (3 given) > >Yes, this is basically broken on all GUIs except GTK*. There was a >fair amount of discussion back in octover on the devel list about how >to do this right, since basically it requires a child to call a method >on the parent and we don't know a-priori what the container will be. >In pylab we can make it work (but haven't yet across backends) because >we know the parent will be a FigureManager instance, but it would be >nice to come up with a generic method that works regardless of whether >you are using mpl in pylab or not. It's on the slow burner, >currently. > >JDH > > >------------------------------------------------------- >This SF.net email is sponsored by: Splunk Inc. Do you grep through log files >for problems? Stop! Download the new AJAX search engine that makes >searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! >http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642 >_______________________________________________ >Matplotlib-devel mailing list >Mat...@li... >https://lists.sourceforge.net/lists/listinfo/matplotlib-devel |
From: Fernando P. <Fer...@co...> - 2006-01-23 17:59:16
|
Ted Drain wrote: > John & Fernando, > I think the basic problem can be solved in a number of ways. Normally a > GUI widget will have an initial size and when it is placed in a window, the > window will layout around it (or to it's own size). However, once the > window is drawn, changing the size of one or more widget that it contains > doesn't mean you're changing the size of the window. > > Here's some ideas for how to fix this: Thanks for the feedback, Ted. I hope one of your suggestions can be implemented (2 sounds very reasonable). If not, at least I think the 'forward' option should then just be removed. There's no point in exposing a feature known to crash all but ONE backend, I think. Regards, f |
From: Ted D. <ted...@jp...> - 2006-01-25 15:55:57
|
Maybe one of you guys could refresh my memory. What is the calling sequence we're going for? Ted At 09:58 AM 1/23/2006, Fernando Perez wrote: >Ted Drain wrote: >>John & Fernando, >>I think the basic problem can be solved in a number of ways. Normally a >>GUI widget will have an initial size and when it is placed in a window, >>the window will layout around it (or to it's own size). However, once >>the window is drawn, changing the size of one or more widget that it >>contains doesn't mean you're changing the size of the window. >>Here's some ideas for how to fix this: > >Thanks for the feedback, Ted. I hope one of your suggestions can be >implemented (2 sounds very reasonable). If not, at least I think the >'forward' option should then just be removed. There's no point in >exposing a feature known to crash all but ONE backend, I think. > >Regards, > >f Ted Drain Jet Propulsion Laboratory ted...@jp... |
From: Fernando P. <Fer...@co...> - 2006-01-25 19:08:11
|
Ted Drain wrote: > Maybe one of you guys could refresh my memory. What is the calling > sequence we're going for? My original message was this: ============================================================================ In [1]: gcf().set_figsize_inches((8,8),forward=True) --------------------------------------------------------------------------- exceptions.TypeError Traceback (most recent call last) /home/fperez/code/python/pylab/arrows/<ipython console> /usr/lib/python2.3/site-packages/matplotlib/figure.py in set_figsize_inches(self, *args, **kwargs) 266 canvasw = w*dpival 267 canvash = h*dpival --> 268 self.canvas.resize(int(canvasw), int(canvash)) 269 270 def get_size_inches(self): TypeError: resize() takes exactly 2 arguments (3 given) A quick look at the backends code shows this: def resize(self, event): width, height = event.width, event.height self.toolbar.configure(width=width) # , height=height) So quite obviously, this doesn't work: it's expecting an event object, and a pair of numbers is being passed. I'm not sure what the proper fix should be here, I don't really know the code flow well enough. I should also note that the gcf().set_figsize_inches((8,8),forward=True) seems to produce a different on-screen result per backend (in some it doesn't do anything, in Qt it stretches the figure only horizontally, ...) That code seems to be pretty much broken. I noticed that figure(figsize=(8,8)) seems to work fine, but I'm not sure how to programmatically resize an existing figure, given the above problems. ============================================================================ Beyond this, I'll leave it to the backend experts as to what the right choices should be. I just noted that shipping a feature _known_ to break on all but one backend doesn't sound like the best approach :) Cheers, f |
From: Ted D. <ted...@jp...> - 2006-01-27 16:17:49
|
Fernando, This looks like you're using the Tk backend. This is one of the problems with trying to use a very common method name in widgets like resize(). Different GUI packages can define it differently. It looks like Tk uses this for it's resize event handling while Gtk and Qt use resize( w, h ) for controlling size and other method names for the event handling like resizeEvent(). After some digging, I think this looks like it might be a bug (or at least a head ache) in the Tk backend design. In backend_bases.py, there is this code: class FigureCanvasBase: ... def resize(self, w, h): """ set the canvas size in pixels """ pass Presumably, this is sort of a default implementation for a virtual method that others can rely on. However, in backends/backend_tkagg.py we have this: class FigureCanvasTkAgg(FigureCanvasAgg): ... def resize(self, event): width, height = event.width, event.height ... And if you look in backends/backend_agg.py you'll see this: class FigureCanvasAgg(FigureCanvasBase): ... So FigureCanvasTkAgg is inheriting from FigureCanvasAgg which inherits from FigureCanvasBase which has a resize( w, h ) method. However, FigureCanvasTkAgg re-implements resize with a different signature. At best this very confusing. It looks like FigureCanvasTkAgg.resize is used as a callback in the ctor for that class for one of the Tk events. Here's what I'd suggest: 1) Rename FigureCanvasTkAgg.resize( event ) to FigureCanvasTkAgg.resize( w, h ). 2) Move the code that extracts the w, h from the event to a new method FigureCanvasTkAgg.resizeEvent( event ) like this: class FigureCanvasTkAgg: def resizeEvent(self, event): width, height = event.width, event.height if self._resize_callback is not None: self._resize_callback(event) self.resize( width, height ) 3) Change the FigureCanvasTkAgg ctor to use the resizeEvent callback instead of resize. WARNING: I don't know anything about Tk! I'm hoping someone that does now Tk can check this over and make sure it sounds right. This of course doesn't actually do anything for fixing the problem we've been discussing about how to resize a plot after it's been created and have the window update accordingly. Ted At 11:08 AM 1/25/2006, Fernando Perez wrote: >Ted Drain wrote: >>Maybe one of you guys could refresh my memory. What is the calling >>sequence we're going for? > >My original message was this: > >============================================================================ >In [1]: gcf().set_figsize_inches((8,8),forward=True) >--------------------------------------------------------------------------- >exceptions.TypeError Traceback (most recent >call last) > >/home/fperez/code/python/pylab/arrows/<ipython console> > >/usr/lib/python2.3/site-packages/matplotlib/figure.py in >set_figsize_inches(self, *args, **kwargs) > 266 canvasw = w*dpival > 267 canvash = h*dpival >--> 268 self.canvas.resize(int(canvasw), int(canvash)) > 269 > 270 def get_size_inches(self): > >TypeError: resize() takes exactly 2 arguments (3 given) > > >A quick look at the backends code shows this: > > def resize(self, event): > width, height = event.width, event.height > self.toolbar.configure(width=width) # , height=height) > >So quite obviously, this doesn't work: it's expecting an event object, and a >pair of numbers is being passed. > >I'm not sure what the proper fix should be here, I don't really know the code >flow well enough. > >I should also note that the gcf().set_figsize_inches((8,8),forward=True) seems >to produce a different on-screen result per backend (in some it doesn't do >anything, in Qt it stretches the figure only horizontally, ...) That code >seems to be pretty much broken. > >I noticed that figure(figsize=(8,8)) seems to work fine, but I'm not sure how >to programmatically resize an existing figure, given the above problems. >============================================================================ > >Beyond this, I'll leave it to the backend experts as to what the right >choices should be. I just noted that shipping a feature _known_ to break >on all but one backend doesn't sound like the best approach :) > >Cheers, > >f Ted Drain Jet Propulsion Laboratory ted...@jp... |
From: Fernando P. <Fer...@co...> - 2006-01-30 06:24:44
|
Hi Ted, Ted Drain wrote: > Fernando, > This looks like you're using the Tk backend. This is one of the problems > with trying to use a very common method name in widgets like > resize(). Different GUI packages can define it differently. It looks like > Tk uses this for it's resize event handling while Gtk and Qt use resize( w, > h ) for controlling size and other method names for the event handling like > resizeEvent(). > > After some digging, I think this looks like it might be a bug (or at least > a head ache) in the Tk backend design. In backend_bases.py, there is this > code: [snip detailed look at the problem] Thanks for the detective work: I was mostly reporting the issue as a TkAgg backend user. I certainly hope that the backend developers can use your info and track this problem down in a clean manner, as this is obviously broken, but I don't know anything about Tk either (I just use it), so I'm afraid I won't be the one doing the work :) Cheers, f |