Matplotlib/wxpython: co-ordinate values not showing up in status bar - python

I have a simple matplotlib plot integrated with wxPython, and for some reason the x/y co-ordinates are not showing up under the status bar (the co-ordinates that show when you move the mouse), they used to appear but cannot get it to happen anymore. Any ideas why this may be possible? (I've also tried setting the format_coord attribute manually but that doesn't seem to work).
I think it's wx doing something funny, since if I just create a matplotlib plot in a new Python shell it works fine. Example code is below:
#Subclassing WX Panel Class to be able to integrate matplotlib into it
class p1(wx.Panel):
def __init__(self, parent, frame):
#Initialize WX Panel
wx.Panel.__init__(self, parent, -1, size=(50,50))
#Set up Figure/Canvas
self.frame = frame
self.figure = Figure()
self.canvas = FigureCanvas(self, -1, self.figure)
#Set up Matplotlib Toolbar
self.chart_toolbar = NavigationToolbar2Wx(self.canvas)
tw,th = self.chart_toolbar.GetSizeTuple()
fw,fh = self.canvas.GetSizeTuple()
self.chart_toolbar.SetSize(wx.Size(fw, th))
self.chart_toolbar.Realize()
graphs_sizer = wx.BoxSizer(wx.VERTICAL)
graphs_sizer.Add(self.canvas, 20, flag=wx.EXPAND, border=5)
graphs_sizer.Add(self.chart_toolbar, 1, flag=wx.ALIGN_CENTER, border=5)
self.SetSizer(graphs_sizer)
def plot(self):
self.axs1 = self.figure.add_subplot(1,1,1)
self.axs1.plot([1,2,3,4,5],color='blue')
class TestFrame(wx.Frame):
def __init__(self, parent, title):
#Initialize WX Frame
wx.Frame.__init__(self, parent, title=title, size=(1000,800))
#Create Splitter Window and Add Left/Right Panels
self.splitterWindow = wx.SplitterWindow(self)
self.panel1 = p1(self.splitterWindow, self)
self.panel2 = wx.Panel(self.splitterWindow)
self.splitterWindow.SplitVertically(self.panel1, self.panel2, 700)
#Create Status Bar
self.statusbar = self.CreateStatusBar()
#Plot
self.panel1.plot()
app = wx.App(redirect=False)
frame = TestFrame(None, "Test")
frame.Show(True)
app.MainLoop()
whereas something as simple as this works fine:
plt.plot([1,2,3,4,5])
plt.show()

It is easier for people to help if you make the code complete, i.e. with the imports in your case.
Note that you don't need the "SetSize" stuff for the toolbar, IIRC that was only needed with some wxPython versions on MAC.
To get the mouse coordinates you need to connect an event, that might be done out of the box with plt.plot.
Doc for the events is here: http://matplotlib.org/users/event_handling.html
import wx
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
#Subclassing WX Panel Class to be able to integrate matplotlib into it
class p1(wx.Panel):
def __init__(self, parent, frame):
#Initialize WX Panel
wx.Panel.__init__(self, parent, -1, size=(50,50))
#Set up Figure/Canvas
self.frame = frame
self.figure = Figure()
self.canvas = FigureCanvas(self, -1, self.figure)
#Set up Matplotlib Toolbar
self.chart_toolbar = NavigationToolbar2Wx(self.canvas)
self.chart_toolbar.Realize()
graphs_sizer = wx.BoxSizer(wx.VERTICAL)
graphs_sizer.Add(self.canvas, 20, flag=wx.EXPAND, border=5)
graphs_sizer.Add(self.chart_toolbar, 1, flag=wx.ALIGN_CENTER, border=5)
self.SetSizer(graphs_sizer)
def plot(self):
self.axs1 = self.figure.add_subplot(1,1,1)
self.axs1.plot([1,2,3,4,5],color='blue')
class TestFrame(wx.Frame):
def __init__(self, parent, title):
#Initialize WX Frame
wx.Frame.__init__(self, parent, title=title, size=(1000,800))
#Create Splitter Window and Add Left/Right Panels
self.splitterWindow = wx.SplitterWindow(self)
self.panel1 = p1(self.splitterWindow, self)
self.panel2 = wx.Panel(self.splitterWindow)
self.splitterWindow.SplitVertically(self.panel1, self.panel2, 700)
#Create Status Bar
self.statusbar = self.CreateStatusBar()
#Plot
self.panel1.plot()
mouseMoveID = self.panel1.canvas.mpl_connect('motion_notify_event',
self.onMotion)
def onMotion(self, evt):
x = evt.x
y = evt.y
inaxes = evt.inaxes
xdata = evt.xdata
ydata = evt.ydata
self.statusbar.SetStatusText("%s, %s, %s, %s, %s" % (
x, y, inaxes, xdata, ydata))
app = wx.App(redirect=False)
frame = TestFrame(None, "Test")
frame.Show(True)
app.MainLoop()

Related

Different matlibplots for different popup choices in wx

I am making a simple gui for a signal generator with wx. I want to display a small plot of say a sine wave when the option "Sine" is chosen, and a plot of a square wave when "Square" is chosen from the menu. I am a newbie in python, and therefore the classes and inheritance of these is difficult for me.
In the (much stripped down) code i have a variable 'wave' inside the class 'ServelPanel' that holds which wavetype is chosen. However, when I try and plot the waveform in the MainFrame class, I cannot for the life of me retrieve the 'wave'-variable. I have tried to inherit classes, set the 'wave'-variable global, and am out of ideas.
import wx, random, math, os
from pyo import *
from numpy import arange, sin, pi, sign
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as
FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
class BasePanel(wx.Panel):
def __init__(self, parent, title):
wx.Panel.__init__(self, parent, style=wx.SUNKEN_BORDER)
self.SetMaxSize((230,150))
self.sliders = []
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.titleSizer = wx.BoxSizer(wx.HORIZONTAL)
self.close = wx.StaticText(self, id=-1, label="X")
self.close.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
self.titleSizer.Add(self.close, 0, wx.LEFT, 5)
self.title = wx.StaticText(self, id=-1, label=title)
off = (210 - self.title.GetSize()[0]) / 2
self.titleSizer.Add(self.title, 0, wx.LEFT, off)
self.sizer.Add(self.titleSizer, 0, wx.BOTTOM|wx.TOP, 4)
class ServerPanel(wx.Panel):
def __init__(self, parent, colour="#DDDDE7"):
wx.Panel.__init__(self, parent, style=wx.SUNKEN_BORDER)
self.SetBackgroundColour(colour)
self.SetMinSize((230,250))
self.fileformat = self.wavetype = 0
self.title = wx.StaticText(self, id=-1, label="--- Simple Wave
Generator ---", pos=(40,5))
font, psize = self.title.GetFont(),
self.title.GetFont().GetPointSize()
font.SetPointSize(psize-2)
self.waveText =
wx.StaticText(self,id=-1,label="Waveform",pos(15,60))
self.popupWave = wx.Choice(self, id=wx.ID_ANY, pos=(13,70),
size(70,20), choices=["Sine","Square"])
self.popupWave.Bind(wx.EVT_CHOICE, self.changeWave)
objs = [self.waveText]
for obj in objs:
obj.SetFont(font)
def changeWave(self, evt):
global wave
wave = evt.GetInt()
if wave == 1: wave = 2
self.wavetype = wave
class MainFrame(wx.Frame,ServerPanel):
def __init__(self, parent=None, title=u"Sine Test", size=(250,300)):
wx.Frame.__init__(self, parent, id=-1, title=title, size=size)
self.server = Server().boot()
self.sizer = wx.FlexGridSizer(4,4,0,0)
self.panel = wx.Panel(self)
self.serverPanel = ServerPanel(self.panel)
self.sizer.Add(self.serverPanel)
self.panel.SetSizer(self.sizer)
pan = CanvasPanel(self.panel)
pan.draw()
self.Show()
class CanvasPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=-1, pos=wx.Point(100,60),
size=wx.Size(80, 50))
figsize = (80*1.0/80, 50*1.0/80)
self.figure = Figure(figsize, dpi=80)
self.axes = self.figure.add_subplot(111)
self.axes.set_axis_off()
self.canvas = FigureCanvas(self, -1, self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas,1,wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
def draw(self):
t = arange(0.0, 3.0, 0.01)
s = sin(2 * pi * t)
self.axes.plot(t, s)
def drawSqr(self):
t = arange(0.0, 3.0, 0.01)
s = sign(sin(2 * pi * t))
self.axes.plot(t, s)
mainFrame = MainFrame()
app.MainLoop()
Ps: I know the "minimal working example" is not really minimal, but it's what I could get working for the moment. Please excuse a novice.
In the example I have hard coded a drawing to show in the MainFrame class, so you see where the drawing should be.
If we boil your code down a bit, remove un-needed classes, use sizers rather than mixing sizers and positional statements, clean up the indentation issues, remove undeclared items and unused imports.
We get something along these lines.
import wx
from numpy import arange, sin, pi, sign
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
class MainFrame(wx.Frame):
def __init__(self, parent=None, title=u"Sine Test", size=(250,300)):
wx.Frame.__init__(self, parent, id=-1, title=title, size=size)
self.panel = wx.Panel(self,-1,style=wx.SUNKEN_BORDER)
self.panel.SetBackgroundColour("#DDDDE7")
self.panel.SetMinSize((230,250))
self.wavetype = 0
self.title = wx.StaticText(self.panel, id=-1, label="--- Simple Wave Generator ---")
font, psize = self.title.GetFont(), self.title.GetFont().GetPointSize()
font.SetPointSize(psize-2)
self.waveText = wx.StaticText(self.panel,id=-1,label="Waveform")
self.popupWave = wx.Choice(self.panel, id=wx.ID_ANY, size=(70,30), choices=["Sine","Square"])
self.popupWave.Bind(wx.EVT_CHOICE, self.changeWave)
self.pan = CanvasPanel(self)
self.sizer = wx.GridBagSizer(hgap=5,vgap=5)
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.title, pos=(0,0), span=(1,4), flag = wx.ALL|wx.ALIGN_CENTER)
self.sizer.Add(self.waveText, pos=(2,0), flag = wx.ALL)
self.sizer.Add(self.popupWave, pos=(3,0), flag = wx.ALL)
self.sizer.Add(self.pan, pos=(3,1), span=(3,3), flag = wx.ALL|wx.EXPAND)
self.panel.SetSizer(self.sizer)
self.main_sizer.Add(self.panel,1,wx.EXPAND)
self.SetSizer(self.main_sizer)
self.popupWave.SetSelection(0)
self.pan.wavetype = self.popupWave.GetSelection()
self.pan.draw()
self.Show()
def changeWave(self, evt):
wave = evt.GetSelection()
self.pan.wavetype = wave
self.pan.draw()
class CanvasPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=-1, size=wx.Size(80, 50))
figsize = (80*1.0/80, 50*1.0/80)
self.figure = Figure(figsize, dpi=80)
self.wavetype = parent.wavetype
self.axes = self.figure.add_subplot(111)
self.axes.set_axis_off()
self.canvas = FigureCanvas(self, -1, self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas,1,wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
def draw(self):
#Clear any previous data
self.axes.clear()
self.axes.set_axis_off()
#Plot new wave
if self.wavetype == 0:
t = arange(0.0, 3.0, 0.01)
s = sin(2 * pi * t)
self.axes.plot(t, s)
else:
t = arange(0.0, 3.0, 0.01)
s = sign(sin(2 * pi * t))
self.axes.plot(t, s)
self.Layout()
app=wx.App()
mainFrame = MainFrame()
app.MainLoop()
It may not be exactly what you are after, so feel free to play with it!

matplotlib Embedded in wxPython with Navigation Toolbar Coordinates

I've come across and implemented a few scripts with matplotlib figures embedded in a wxPython panel. The embedding of the actual plot is fine but when I add a navigation toolbar NavigationToolbar2WxAgg much of the toolbar functionality is lost. I can pan and zoom, but there are no coordinates displayed, and the default shortcut keys do not work. The same behavior occurs in embedding_in_wx4_sgskip.py from the example/user_interfaces folder for matplotlib:
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar
from matplotlib.figure import Figure
import numpy as np
import matplotlib as mpl
import wx
import wx.lib.mixins.inspection as WIT
class CanvasFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
'CanvasFrame', size=(550, 350))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2 * np.pi * t)
self.axes.fmt_xdata = lambda x: "{0:f}".format(x)
self.axes.fmt_ydata = lambda x: "{0:f}".format(x)
self.axes.plot(t, s)
self.canvas = FigureCanvas(self, -1, self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
self.SetSizer(self.sizer)
self.Fit()
self.add_toolbar() # comment this out for no toolbar
def add_toolbar(self):
self.toolbar = NavigationToolbar(self.canvas)
self.toolbar.Realize()
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
# alternatively you could use
#class App(wx.App):
class App(WIT.InspectableApp):
def OnInit(self):
'Create the main window and insert the custom frame'
self.Init()
frame = CanvasFrame()
frame.Show(True)
return True
app = App(0)
app.MainLoop()
How do I restore or add this functionality to my navigation bar?
You can put this code here:
#Create 'Position Display'
self.Text = wx.StaticText( self, wx.ID_ANY, u" Available Channels ", wx.DefaultPosition, wx.DefaultSize, 0 )
self.Text.Wrap( -1 )
mouseMoveID = self.canvas.mpl_connect('motion_notify_event',
self.onMotion)
Before you create your sizer. Then add this to the end of your init definition:
self.sizer.Add(self.Text,0, wx.LEFT | wx.EXPAND)
Finally, add this function to capture mouse movement on the frame:
def onMotion(self, evt):
"""This is a bind event for the mouse moving on the MatPlotLib graph
screen. It will give the x,y coordinates of the mouse pointer.
"""
xdata = evt.xdata
ydata = evt.ydata
try:
x = round(xdata,4)
y = round(ydata,4)
except:
x = ""
y = ""
self.Text.SetLabelText("%s (s), %s" % (x,y))
This is what worked for me, good luck!

Bigger matplot figure in a ScrolledWindow or ScrolledPanel

I'd like plot a figure(having many subfigures) in a scrolledwindow(or scrolledpanel).
figure width depends on the width of window and figure height is calculated like width * 2.
if the height of window ls less than width * 2, scrollbar of window is enabled.
with the following code, I checked the size of figure, canvas and window.
the height of figure and figure is bigger than the height of window. but scrollbar is not enabled.
I tried with boxsizer also, but it did not work.
Can you make this code work?
from matplotlib.backends.backend_wxagg import \
FigureCanvasWxAgg as FigureCanvas, \
NavigationToolbar2WxAgg as NavigationToolbar
from matplotlib.figure import Figure
import numpy as np
import wx
from wx.lib.scrolledpanel import ScrolledPanel
class MyFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=title,
pos=wx.DefaultPosition, size=wx.Size(200, 300))
# self.T_panel = wx.Panel(self)
# self.T_wd = wx.ScrolledWindow(self.T_panel, -1, wx.DefaultPosition,
# wx.DefaultSize, wx.VSCROLL|wx.ALWAYS_SHOW_SB)
self.T_wd = ScrolledPanel(self, -1, size=wx.Size(200, 300))
self.Bind(wx.EVT_SIZE, self.onSize)
self.T_wd.SetupScrolling()
self.T_fig = Figure((5.0,5.0), dpi=80)
self.T_canvas = FigureCanvas(self.T_wd, -1, self.T_fig)
self.graph = self.T_fig.add_subplot(111)
self.T_wd.Layout()
def onSize(self, event):
size = event.GetSize()
x = np.arange(5)
y = np.random.rand(5) * 5.
self.T_fig.set_size_inches(size[0]/80., size[0]/40.)
self.T_canvas.SetSize((size[0], size[0]*2))
self.graph.hold(False)
self.graph.plot(x,y)
self.T_canvas.draw()
self.T_wd.SetSize(size)
self.T_wd.SetupScrolling()
print 'event size', size
print 'fig size', self.T_fig.get_size_inches()*80
print 'canvas size', self.T_canvas.GetSize()
print 'window(panel) wize', self.T_wd.GetSize()
print ''
class my_App(wx.App):
def OnInit(self):
frame = MyFrame(None, title = 'test')
frame.Show(True)
self.SetTopWindow(frame)
return True
my_App().MainLoop()

Scrollbar disappears / refresh not working in wx.python

In the following example the scrollbar disappears after using the calculating button, although the layout function was called. If you manually resize the frame it reappears. This behavior occurs only under windows, in linux the scrollbar functions as it should.
To fix it I tried the functions refresh() and update() (in layout funtion of class GUI_Diagrams_GHL) - but it didn't help.
I tried to reduce my application to this minmal working example:
# -*- coding: utf-8 -*-
import wx
from wx.lib.pubsub import pub
import wx.lib.scrolledpanel as scrolled
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
class MainWindow(wx.Frame):
'''Frame that contains pretty much everything'''
def __init__(self,*args,**kwargs):
'''Constructor'''
super(MainWindow,self).__init__(*args,**kwargs)
self.panel = wx.Panel(self)
notebook = Notebook(self.panel)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(notebook,1, wx.ALL|wx.EXPAND,4)
self.panel.SetSizerAndFit(sizer)
self.panel.Layout()
class Notebook(wx.Notebook):
def __init__(self, parent):
wx.Notebook.__init__(self, parent, id=wx.ID_ANY, style = wx.BK_DEFAULT)
tabTwo = GUI_Input_GHL(self)
self.AddPage(tabTwo, 'Input')
tabThree = GUI_Diagrams_GHL(self)
self.AddPage(tabThree, 'Diagrams')
class GUI_Input_GHL(scrolled.ScrolledPanel):
"""This panel contains the input fields for basic data."""
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent=parent, id=wx.ID_ANY)
self.label_1 = wx.StaticText(self,-1,label=u'Label 1')
self.button2 = wx.Button(self,-1,label=u'Start')
self.Bind(wx.EVT_BUTTON, self.StartCalc, self.button2)
self.layout()
def layout(self):
sizer = wx.GridBagSizer()
sizer.Add(self.button2, (8,0),(2,3), flag =wx.EXPAND)
sizer.Add(self.label_1, (0,0),flag=wx.ALIGN_CENTER_VERTICAL)
self.SetAutoLayout(1)
self.SetupScrolling()
self.SetSizerAndFit(sizer)
def StartCalc(self,event):
pub.sendMessage('GUI_Diagrams_Listener', message = 'test')
class GUI_Diagrams_GHL(scrolled.ScrolledPanel):
"""This panel contains diagrams"""
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent=parent, id=wx.ID_ANY)
self.parent = parent
self.fig1 = Figure()
self.fig6 = Figure()
self.canvas1 = FigCanvas(self,-1,self.fig1)
self.axes1 = self.fig1.add_subplot(111)
self.canvas6 = FigCanvas(self,-1,self.fig6)
self.axes6 = self.fig6.add_subplot(111)
self.dia_R_hat_SetValues('test')
self.dia_theta_SetValues('test')
self.layout()
pub.subscribe(self.diagrams_SetValues, "GUI_Diagrams_Listener")
def layout(self):
sizer = wx.GridBagSizer()
sizer.Add(self.canvas1, (1,0), (12,12), wx.EXPAND)
sizer.Add(self.canvas6, (53,0), (12,12), wx.EXPAND)
## I guess here is the problem somewhere:
self.SetSizerAndFit(sizer)
self.SetAutoLayout(1)
self.SetupScrolling()
#self.Fit()
#self.Layout()
#self.FitInside()
#self.AlwaysShowScrollbars(True,True)
#self.Refresh()
#self.Update()
#self.parent.SetSize(self.parent.GetSize())
def diagrams_SetValues(self, message):
self.Output = message
self.dia_R_hat_SetValues(message)
self.dia_theta_SetValues(message)
self.layout()
def dia_R_hat_SetValues(self, Output):
self.axes1.clear()
self.axes1.plot(range(15),range(15), 'r-', linewidth = 2)
self.canvas1.draw()
def dia_theta_SetValues(self, Output):
self.axes6.clear()
self.axes6.plot(range(5),'k')
self.axes6.set_title(r"Absolute Temperature")
self.canvas6.draw()
if __name__ == '__main__':
app = wx.App()
frame = MainWindow(None, -1, 'MyApp')
frame.Show()
app.MainLoop()
I've figured it out myself :)
If you call the layout function of the main panel ('MainWindow.panel.Layout()') after updating the diagrams/in the layout of the diagram class, the whole panel refreshes and
the Scrollbars reappear. So a 'parent.parent.Layout()' worked for me in this case.
Any other suggestions/solutions?

matplotlib: how to refresh figure.canvas

I can't understand how to refresh FigureCanvasWxAgg instance. Here is the example:
import wx
import matplotlib
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.NewId(), "Main")
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.figure = Figure(figsize=(1,2))
self.axe = self.figure.add_subplot(111)
self.figurecanvas = FigureCanvas(self, -1, self.figure)
self.buttonPlot = wx.Button(self, wx.NewId(), "Plot")
self.buttonClear = wx.Button(self, wx.NewId(), "Clear")
self.sizer.Add(self.figurecanvas, proportion=1, border=5, flag=wx.ALL | wx.EXPAND)
self.sizer.Add(self.buttonPlot, proportion=0, border=2, flag=wx.ALL)
self.sizer.Add(self.buttonClear, proportion=0, border=2, flag=wx.ALL)
self.SetSizer(self.sizer)
self.figurecanvas.Bind(wx.EVT_LEFT_DCLICK, self.on_dclick)
self.buttonPlot.Bind(wx.EVT_BUTTON, self.on_button_plot)
self.buttonClear.Bind(wx.EVT_BUTTON, self.on_button_clear)
self.subframe_opened = False
def on_dclick(self, evt):
self.subframe = SubFrame(self, self.figure)
self.subframe.Show(True)
self.subframe_opened = True
def on_button_plot(self, evt):
self.axe.plot(range(10), color='green')
self.figurecanvas.draw()
def on_button_clear(self, evt):
if self.subframe_opened:
self.subframe.Close()
self.figure.set_canvas(self.figurecanvas)
self.axe.clear()
self.figurecanvas.draw()
class SubFrame(wx.Frame):
def __init__(self, parent, figure):
wx.Frame.__init__(self, parent, wx.NewId(), "Sub")
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.figurecanvas = FigureCanvas(self, -1, figure)
self.sizer.Add(self.figurecanvas, proportion=1, border=5, flag=wx.ALL | wx.EXPAND)
self.SetSizer(self.sizer)
self.Bind(wx.EVT_CLOSE, self.on_close)
def on_close(self, evt):
self.GetParent().subframe_opened = False
evt.Skip()
class MyApp(wx.App):
def OnInit(self):
frame = MainFrame()
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()
I'm interested in the following sequence of operations:
run a script
resize the main frame
press Plot button
double click on plot
press Clear button
Now I get a mess on main frame plot. If I resize the frame it redraws properly. My question is what should I add to my code to do that without resizing?
By a "mess" I mean something like this:
http://img227.imageshack.us/img227/5407/mess.png
Thanks in advance.
As I said in the comments, I don't think that the figure canvas refresh is your problem, in fact I think it's doing exactly what it's supposed to (redrawing itself based on it's last state [ie as it was in your subplot]). I think your problem is more that the wxFrame is not refreshing.
The easiest way to fix that would be to make it resize itself on your "Clear" event. Something like:
def on_button_clear(self, evt):
if self.subframe_opened:
self.subframe.Close()
self.figure.set_canvas(self.figurecanvas)
self.axe.clear()
self.figurecanvas.draw()
self.SetSize((self.Size[0],self.figurecanvas.Size[1]))
The set size would cause the frame and all the controls it contains to be redrawn.
That said, I think sharing your figure between the two figurecanvas is dangerous. I was able to produce some serious errors by clicking/resizing things in different combinations. On occasion your figure would be garbage collected when the subframe was closed, making it unavailable to your main frame.

Categories