Repository navigation
Closed
Milestone
Description
I have seen a problem on more than one Mac running OS X 10.9.x where MPL images are not updated properly. As one example of this, when one zooms a plot, by selecting the zoom widget, the rectangle is never erased and after it is "released" the plot is never redrawn with the new limits. This happens when I embed a figure into a wx Panel, as shown in the script below.
I do not see the problem with EPD (python 2.7.3, wxpython 2.8.10.1, matplotlib 1.1.0), but do with fairly recent Anaconda (python 2.7.8, wxpython 3.0.0.0, matplotlib 1.4.2) and Canopy (python 2.7.6, wxpython 2.9.2.4, matplotlib 1.3.1) dists.
# simple demo that fails on Mac (at least on 10.9.5) and later wx/mpl combos
#
# problem is that if one selects the zoom button and drags a region,
# the rectangles never disappear and the image is not updated to
# show the zoomed in region
#
# works (not quite 100%) w/EPD (python 2.7.3, wxpython 2.8.10.1, matplotlib 1.1.0)
# fails w/Anaconda (python 2.7.8, wxpython 3.0.0.0, matplotlib 1.4.2
# fails w/Canopy (python 2.7.6, wxpython 2.9.2.4, matplotlib 1.3.1)
#
import sys
import wx
import wx.aui
import matplotlib as mpl
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as mplCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as mplToolbar
print "python: ",sys.version[:5]
print "wxpython: ",wx.__version__
print "matplotlib: ",mpl.__version__
app = wx.PySimpleApp()
# create frame with notebook
frame = wx.Frame(None, size=(400,400))
win = wx.Panel(frame)
win.nb = wx.aui.AuiNotebook(win)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(win.nb, 1, wx.EXPAND)
win.SetSizer(sizer)
# create a panel for the plot with a plot in it
tab = wx.Panel(win.nb, id=-1)
figure = mpl.figure.Figure(dpi=None)
# create a quick figure for the plot
ax = figure.gca()
ax.plot(range(10),range(10),'o-')
canvas = mplCanvas(tab, -1, figure)
toolbar = mplToolbar(canvas)
toolbar.Realize()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(canvas,1,wx.EXPAND)
sizer.Add(toolbar, 0 , wx.LEFT | wx.EXPAND)
tab.SetSizer(sizer)
win.nb.AddPage(tab,'plot1') # add the panel as a notebook tab
frame.Show()
app.MainLoop()

Activity
briantoby commentedon Nov 26, 2014
I have spent some more time on this and have noticed that in _onDrawIdle() in backend_wx.py, the wx.GetApp().Pending() call seems to always evaluate as True.
I have also seen that I can find a similar bug in Windows w/only 64 bit wx, where after the first zoom, home or arrow use, .Pending also never stops returning as True.
Patching draw_idle() to call self.draw() directly seems to solve at least some of the problems:
I suspect this causes other problems. This also does not address the uglyness when dragging the zoom box.
RobinD42 commentedon Dec 1, 2014
The docstring for
draw_idleis: "Delay rendering until the GUI is idle." To do that in wx you do not need to mess withPendingand timers at all. Simply usingRefreshwill do basically the same thing. It causes the system to add a paint event to the queue, but it will not be processed immediately. It will typically be delayed until there are no other pending events, or until painting is forced for some reason. On OSX the paint event will be scheduled into the active display pipeline so it will happen at the best possible moment taking the whole display into account.On a former job I worked around this issue by subclassing FigureCanvasWxAgg and overriding draw_idle like this:
It worked well for at least the use cases needed by that application (several histogram, scatter and img plots) and was tested on Windows and OSX. wxGTK ports should also do fine with this change.
NOTE: the above will not fix the trails left behind while dragging the rubberband. I have another fix for that which I'll try to track down.
RobinD42 commentedon Dec 1, 2014
To get a better rubberband effect that also doesn't leave trails on OSX, you can use a
wx.Overlayinstead of directly drawing to awx.ClientDC(which is just a bad idea in most cases these days.) I've implemented this in an old project by overriding the following methods in a class derived fromNavigationToolbar2Wx. This should work in at least wxPython 2.8.12, 2.9, and 3.0+, and possibly earlier 2.x versions. You may want to encorporate these changes directly intoNavigationToolbar2Wx.efiring commentedon Dec 1, 2014
@RobinD42 Thanks very much for the tips. If you would like to turn them into a PR, that would be even better; but if not, I expect they will get in one way or another.
RobinD42 commentedon Dec 2, 2014
Yeah, I figured that would be the first question. 😉
I didn't have time to do a real PR today, but I'll try to do it soonish.
tacaswell commentedon Jan 8, 2015
closed by #3905