Hello,
I already opened a thread which was unfortunately misspelled.
In order to help other users finding this subject I correcr that.
After looking at the hints I received - thanks a lot folks! - I created a sample which works to some extend.
Four questions remain:
1. When I close my application I receive a meesage box.
I have to translate the message box from german so in english the text may differ.
Title: python.exe – Error in application
Text: statement “0x0166b07f” points on memory “0x00000000004”. Read could not be executed in memory.
How to avoid that?
2. When I start my application the crosshair cursor moves but the cursors initial position does not disappear until I leave the axes.
3. I there a better way to update the figure. I have to delete the axes object in order to get my colobar refreshed.
4. If this is found to be a useful sample, who decides whether this sample should be addes to the samples of matplotlib?
Please see the sample below.
Cheers Reinhard
# -*- coding: UTF-8 -*-
from numpy import arange, sin, pi
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.widgets import Cursor, SpanSelector
import pylab
import wx
class ContourFrame(wx.Frame):
'''
ContourFrame is a sample showing how to add a Matplotlib Figure to a
wxPython application.
It should demonstrate how to use a crosshair cursor to select certain lines
or rows in a contour plot.
This frame contains a vertical box sizer holding
- The whole content is in sizerMain (m)
- sizerMain is in posession of sizerVertical (v)
- in the upper region of sizerVertical resides the Matplotlib figure canvas (C)
in the lower region FlexGridSizer sizerHorizontal (f)
- FlexGridSizer sizerHorizontal contains some wx control elements (1, 2, 3, 4, 5, 6)
The sizers are thought to be set as follows
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
m vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv m
m v v m
m v CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC v m
m v CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC v m
m v CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC v m
m v v m
m v ffffffffffffffffffffffffffffffffff v m
m v f f v m
m v f 11111111 222222222 33333333333 f v m
m v f 11111111 222222222 33333333333 f v m
m v f f v m
m v f 44444444 555555555 66666666666 f v m
m v f 44444444 555555555 66666666666 f v m
m v f f v m
m v ffffffffffffffffffffffffffffffffff v m
m vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv m
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
'''
def __init__(self):
'''
construktor of frame object
'''
# 1. Call the constructor of the parent class
wx.Frame.__init__(self, None, -1, 'contour sample with cursor') #, size=(655, 630))
# create the wx status bar
self.statusbar = self.CreateStatusBar()
# Divide the status into three field.
self.statusbar.SetFieldsCount(3)
self.statusbar.SetStatusWidths([-1, -2, -3])
self.statusbar.SetStatusText("Current Position:", 0)
# 2. Lets create some data for contouring utilizing pylab functions (stolen from contourf_demo.py)
delta = 0.025
x = y = arange(-3.0, 3.01, delta)
self.X, self.Y = pylab.meshgrid(x, y)
Z1 = pylab.bivariate_normal(self.X, self.Y, 1.0, 1.0, 0.0, 0.0)
Z2 = pylab.bivariate_normal(self.X, self.Y, 1.5, 0.5, 1, 1)
self.Z = 10 * (Z1 - Z2)
# these values are updated by the sliders
self.factor = 1.0
self.addon = 0.0
# 3. All the matplotlib stuff is done in the following lines. In the end we are in possession of
# a FigureCanvas which we can add to a sizer just like a widget.
# the matplotlib-figure object
self.figure = Figure()
# the matplotlib-axes object is obviously created here
self.axes = self.figure.add_subplot(111)
# annotations found in some web-sample
# Red, Bold, 12pt
self.axes.set_title('A contour plot generated with contourf', color='r', fontweight='bold', fontsize=12)
# Green, `smaller' size
self.axes.set_xlabel('This is the x axis', color='g', fontstyle='oblique', fontsize='greater')
# Italic
self.axes.set_ylabel('This is the x axis', color='b',fontstyle='italic')
# method contourf of the axes objects also stolen from contourf_demo.py
self.contourf = self.axes.contourf(self.X, self.Y, (self.factor * self.Z + self.addon),
cmap=pylab.cm.jet)
self.colorbar = self.figure.colorbar(self.contourf, orientation='horizontal')
# create a FigureCanvas which belongs to our frame and contains our figure object
self.canvas = FigureCanvas(self, -1, self.figure)
self.canvas.draw()
self.cursor = Cursor(self.axes, useblit=True, color='red', linewidth=2 )
# use the Matplotlib bind functionality to bind the cursor move
self.canvas.mpl_connect('motion_notify_event', self.onmousemove)
# 4. Now we are doing the wxpython user interface
# the mainpanel holds all widgets
self.mainpanel = wx.Panel(self, -1)
# Lets create a control element - sliderMultiply
self.sliderMultiply = wx.Slider(self.mainpanel, 100, 1.0, -5.0, 5.0, pos=(10, 10), size=(305, -1),
style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
self.sliderMultiply.SetTickFreq(5, 1)
self.sliderMultiplyName = wx.StaticText (self.mainpanel, -1, 'multiply matrix with')
# and another control element sliderAdd
self.sliderAdd = wx.Slider(self.mainpanel, 100, 0.0, -10.0, 10.0, pos=(10, 10), size=(305, -1),
style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
self.sliderAdd.SetTickFreq(5, 1)
self.sliderAddName = wx.StaticText (self.mainpanel, -1, 'add matrix with')
# Checkboxes ae used to control the visibility of the crosshair cusor
self.CheckBoxHorizontalCursor = wx.CheckBox(self.mainpanel, -1, "horizontal Cursor")
self.CheckBoxHorizontalCursor.SetValue(True)
self.CheckBoxVerticalCursor = wx.CheckBox(self.mainpanel, -1, "vertical Cursor")
self.CheckBoxVerticalCursor.SetValue(True)
# Bind the wx GUI events
# Trigger when a slider or scrollbar change is finished - All sliders and scrollbars are
# controlled by one bind. This is marvellous but thats the way it works.
self.Bind(wx.EVT_SCROLL_ENDSCROLL, self.OnScroll)
self.Bind(wx.EVT_CHECKBOX, self.OnCheckBoxHorizontalCursor, self.CheckBoxHorizontalCursor)
self.Bind(wx.EVT_CHECKBOX, self.OnCheckBoxVerticalCursor, self.CheckBoxVerticalCursor)
# Now we add the wx controls to a FlexGridSizer named sizerHorizontal
self.sizerHorizontal = wx.FlexGridSizer(rows=2, cols=3, hgap=0, vgap=0)
self.sizerHorizontal.Add(self.CheckBoxHorizontalCursor, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_TOP | wx.GROW, 10)
self.sizerHorizontal.Add(self.sliderMultiplyName, 0, wx.ALIGN_CENTER )
self.sizerHorizontal.Add(self.sliderAddName, 0, wx.ALIGN_CENTER)
self.sizerHorizontal.Add(self.CheckBoxVerticalCursor, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_TOP | wx.GROW, 10)
self.sizerHorizontal.Add(self.sliderMultiply, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_TOP | wx.GROW, 10)
self.sizerHorizontal.Add(self.sliderAdd, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_TOP | wx.GROW, 10)
# We add the matplotlib canvas and the horizontal sizer to a vertical BoxSizer
self.sizerVertical = wx.BoxSizer(wx.VERTICAL)
self.sizerVertical.Add(self.canvas, 0, wx.LEFT | wx.BOTTOM | wx.GROW)
self.sizerVertical.Add(self.sizerHorizontal, 0, wx.GROW | wx.ALIGN_CENTER_HORIZONTAL)
# the vertical BoxSizer belongs to the main panel
self.mainpanel.SetSizer(self.sizerVertical)
self.sizerVertical.Fit(self.mainpanel)
self.sizerMain = wx.BoxSizer(wx.VERTICAL)
# create sizerMain which holds all the stuff and fit our frame
self.sizerMain.Add(self.sizerVertical)
self.SetSizer(self.sizerMain)
self.Fit()
def OnScroll(self, evt):
# take the slider value
self.factor = float(self.sliderMultiply.GetValue())
self.addon = float(self.sliderAdd.GetValue())
# clear the figure or delete the axes - I did not find an update for the color bar so I
# create everything again after clearing or deleting it
#self.figure.clf()
self.figure.delaxes(self.axes)
# Once again do all the axes stuff
# the matplotlib-axes object is obviously created here
self.axes = self.figure.add_subplot(111)
# annotations found in some web-sample
# Red, Bold, 12pt
self.axes.set_title('A contour plot generated with contourf', color='r', fontweight='bold', fontsize=12)
# Green, `smaller' size
self.axes.set_xlabel('This is the x axis', color='g', fontstyle='oblique', fontsize='greater')
# Italic
self.axes.set_ylabel('This is the x axis', color='b',fontstyle='italic')
self.contour = self.axes.contourf(self.X, self.Y, (self.factor * self.Z + self.addon))
self.contourf = self.axes.contourf(self.X, self.Y, (self.factor * self.Z + self.addon),
cmap=pylab.cm.jet)
self.colorbar = self.figure.colorbar(self.contourf, orientation='horizontal')
self.cursor = Cursor(self.axes, useblit=True, color='red', linewidth=2 )
self.canvas.draw()
def OnCheckBoxHorizontalCursor(self,event):
# Show or hide the horizontal cursor
boolHorizontalCursor = self.CheckBoxHorizontalCursor.GetValue()
if boolHorizontalCursor == True:
self.cursor.horizOn = True
else:
self.cursor.horizOn = False
def OnCheckBoxVerticalCursor(self,event):
# Show or hide the vertical cursor
boolVerticalCursor = self.CheckBoxVerticalCursor.GetValue()
if boolVerticalCursor == True:
self.cursor.vertOn = True
else:
self.cursor.vertOn = False
def onmousemove(self,event):
# the cursor position is given in the wx status bar
self.figure.gca()
if event.inaxes:
x, y = event.xdata, event.ydata
self.statusbar.SetStatusText("x = %.2f" %x, 1)
self.statusbar.SetStatusText("y = %.2f" %y, 2)
class App(wx.App):
def OnInit(self):
# 'Create the main window and insert the custom frame'
frame = ContourFrame()
frame.Show(True)
return True
app = App(0)
app.MainLoop()