From: Matt N. <new...@ca...> - 2005-03-25 04:50:21
|
Hi Leighton, > The Loop method and custom event methods work fine on Windows. > On Linux, they dynamically update the plot, but not the button > label. On OS X, they do nothing, and only appear to update > the plot after the loops end. I'm no expert in wxPython or matplotlib, but there are a few possible problems with your script: - For the timing method, I think the issue is simply how fast you can send Timer events. You're doing them every 20ms, which is pretty fast (I'm willing to take the blame for sending you an example that goes that fast!). If you change that to 200ms, I'll bet you will see more updates. - The Loop method runs a for-loop which may not allow other wx events to be processed, such as changing a Button label. - The Custom Event uses a python for-loop, so I think it's not very different from the Loop method in that it's liable to drop events. For all these, I would think that adding self.Update() should help. This is supposed to repaint the whole wxWidget. That will take time, but should really update all widgets. But it seems that this is not foolproof, and that it can lose events: I don't know why this is. > Matt's solution works on OS X, but I'm afraid I didn't specify > what my goal was particularly well. I'm aiming to dynamically > update a matplotlib plot embedded within a wx.Panel (or > wx.Frame) from another object, whose internal state is > changing so that the calling object's internal state is > reflected in the matplotlib plot. The wx.Timer solution > doesn't seem appropriate for that (though if I'm wrong, I'm > happy to take advice). > > After some reading around, I worked up two alternatives for > updating the plot from another object. > > 1) wx.Timer, as per Matt > 2) Loop, and pass the value of the loop counter > 3) A custom wx event, bound to the update method I think you want to avoid the Loop method, as it can block other widget events. I believe that what you want is to replot the figure when (a) the data has changed and (b) some minimum time has elapsed since the last drawing. One approach is to use a timer to periodically check (this sets the minimun time) for new data, and redraw the plot when there's new data. Another approach is to trigger on changes in the data, possibly saving the timestamp when a redraw is done so as to not draw too often. Which method to use probably depends on how easily it is to detect and act upon changes to the data. Finally, you may also consider putting the data-intensive code in a separate thread from the GUI. But I think the main issue is to not try to redraw the plot 50 times per second. ;). Hope that helps, --Matt |