I have been bashing my head against the wall trying to update a graph using matplotlib with python and wxpython. I want to press a button and add data to a graph nested in a wx.notebook. Below is the code.
Thanks for the help
import wx
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
class Plot(wx.Panel):
def __init__(self, parent, id = -1, dpi = None, **kwargs):
wx.Panel.__init__(self, parent, id=id, **kwargs)
self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2,2))
self.canvas = Canvas(self, -1, self.figure)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas,1,wx.EXPAND)
self.SetSizer(sizer)
class JBC(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600,600))
self.SetBackgroundColour(wx.Colour(236, 233, 216))
self.nbG = wx.Notebook(self, -1, style=0, size=(400,400), pos=(0,0))
self.gSheet1 = self.add("Test").gca()
calcButton = wx.Button(self, wx.NewId(), "Update", pos=(0, self.nbG.Position.y+400))
#self.gSheet1.hold(False)
#self.gSheet1.set_xlim(0,20)
#self.gSheet1.set_ylim(0,20)
#for i in range (2):
# self.gSheet1.plot([0,10],[1*i,1+i])
#axes2 = plotter.add('figure 2').gca()
#axes2.plot([1,2,3,4,5],[2,1,4,2,3])
self.Bind(wx.EVT_BUTTON, self.OnCalculate, calcButton)
self.Show(True)
def OnCalculate(self, event):
self.gSheet1.set_xlim(0,20)
self.gSheet1.set_ylim(0,20)
self.gSheet1.plot([1,2,3,4,5],[2,1,4,2,3])
self.Update()
def add(self,name="plot"):
page = Plot(self.nbG)
self.nbG.AddPage(page,name)
return page.figure
def Update(self):
self.gSheet1.clear()
plt.draw()
print "Tried to redraw"
app = wx.App()
JBC(None, -1, "Test Title")
app.MainLoop()
Using this example as a guide, perhaps try this:
import wx
import matplotlib as mpl
mpl.use('WXAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
class Plot(wx.Panel):
def __init__(self, parent, id = -1, dpi = None, **kwargs):
wx.Panel.__init__(self, parent, id=id, **kwargs)
self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2,2))
self.canvas = Canvas(self, -1, self.figure)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas,1,wx.EXPAND)
self.SetSizer(sizer)
class JBC(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600,600))
self.SetBackgroundColour(wx.Colour(236, 233, 216))
self.nbG = wx.Notebook(self, -1, style=0, size=(400,400), pos=(0,0))
self.gSheet1 = self.add("Test").gca()
calcButton = wx.Button(self, wx.NewId(), "Update", pos=(0, self.nbG.Position.y+400))
#self.gSheet1.hold(False)
#self.gSheet1.set_xlim(0,20)
#self.gSheet1.set_ylim(0,20)
#for i in range (2):
# self.gSheet1.plot([0,10],[1*i,1+i])
#axes2 = plotter.add('figure 2').gca()
#axes2.plot([1,2,3,4,5],[2,1,4,2,3])
self.Bind(wx.EVT_BUTTON, self.OnCalculate, calcButton)
# self.Show(True)
def OnCalculate(self, event):
self.gSheet1.set_xlim(0,20)
self.gSheet1.set_ylim(0,20)
self.gSheet1.plot([1,2,3,4,5],[2,1,4,2,3])
self.Update()
def add(self,name="plot"):
page = Plot(self.nbG)
self.nbG.AddPage(page,name)
return page.figure
def Update(self):
self.gSheet1.clear()
plt.draw()
print "Tried to redraw"
if __name__ == '__main__':
app = wx.App()
frame=JBC(None, -1, "Test Title")
frame.Show()
app.MainLoop()
It is also possible to use matplotlib to draw an animated figure:
"""
Based on Tkinter bouncing ball code:
http://stackoverflow.com/q/13660042/190597 (arynaq) and
http://eli.thegreenplace.net/2008/08/01/matplotlib-with-wxpython-guis/
"""
import wx
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.figure as mplfig
import scipy.spatial.distance as dist
import matplotlib.backends.backend_wxagg as mwx
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, size = (800, 600))
self.panel = wx.Panel(self)
self.fig = mplfig.Figure(figsize = (5, 4), dpi = 100)
self.ax = self.fig.add_subplot(111)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.canvas = mwx.FigureCanvasWxAgg(self.panel, wx.ID_ANY, self.fig)
self.toolbar = mwx.NavigationToolbar2WxAgg(self.canvas)
self.button = wx.Button(self.panel, wx.ID_ANY, "Quit")
self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.vbox.Add(self.toolbar, 0, wx.EXPAND)
self.vbox.Add(
self.button, 0, border = 3,
flag = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL)
self.panel.SetSizer(self.vbox)
self.vbox.Fit(self)
self.toolbar.update()
self.update = self.animate().next
self.timer = wx.Timer(self)
self.timer.Start(1)
self.Bind(wx.EVT_BUTTON, self.OnCloseWindow, self.button)
self.Bind(wx.EVT_TIMER, lambda event: self.update())
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
def OnCloseWindow(self, evt):
self.timer.Stop()
del self.timer
self.Destroy()
def animate(self):
N = 100 #Number of particles
R = 10000 #Box width
pR = 5 #Particle radius
r = np.random.randint(0, R, (N, 2)) #Position vector
v = np.random.randint(-R/100, R/100, (N, 2)) #velocity vector
a = np.array([0, -10]) #Forces
v_limit = R/2 #Speedlimit
line, = self.ax.plot([], 'o')
line2, = self.ax.plot([], 'o') #Track a particle
self.ax.set_xlim(0, R+pR)
self.ax.set_ylim(0, R+pR)
while True:
v = v+a #Advance
r = r+v
#Collision tests
r_hit_x0 = np.where(r[:, 0]<0) #Hit floor?
r_hit_x1 = np.where(r[:, 0]>R) #Hit roof?
r_hit_LR = np.where(r[:, 1]<0) #Left wall?
r_hit_RR = np.where(r[:, 1]>R) #Right wall?
#Stop at walls
r[r_hit_x0, 0] = 0
r[r_hit_x1, 0] = R
r[r_hit_LR, 1] = 0
r[r_hit_RR, 1] = R
#Reverse velocities
v[r_hit_x0, 0] = -0.9*v[r_hit_x0, 0]
v[r_hit_x1, 0] = -v[r_hit_x1, 0]
v[r_hit_LR, 1] = -0.95*v[r_hit_LR, 1]
v[r_hit_RR, 1] = -0.99*v[r_hit_RR, 1]
#Collisions
D = dist.squareform(dist.pdist(r))
ind1, ind2 = np.where(D < pR)
unique = (ind1 < ind2)
ind1 = ind1[unique]
ind2 = ind2[unique]
for i1, i2 in zip(ind1, ind2):
eps = np.random.rand()
vtot = v[i1, :]+v[i2, :]
v[i1, :] = -(1-eps)*vtot
v[i2, :] = -eps*vtot
line.set_ydata(r[:, 1])
line.set_xdata(r[:, 0])
line2.set_ydata(r[:N/5, 1])
line2.set_xdata(r[:N/5, 0])
self.canvas.draw()
yield True
def main():
app = wx.App(False)
frame = Frame()
frame.Show(True)
app.MainLoop()
if __name__ == '__main__':
main()
Related
How to add all limits value in left side single/single Y-label using matplotlib or pyqtgraph. I've managed a sample chart and attached here.
import wx
import matplotlib
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
class TopPanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self, parent = parent)
self.figure = Figure()
#wx.Button(self,wx.ID_ANY, label="Button 1")
self.SetBackgroundColour("red")
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self,-1,self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.EXPAND)
self.SetSizer(self.sizer)
self.axes.set_xlabel("Time")
self.axes.set_ylabel("A/D Counts")
def draw(self):
x = np.arange(0,5,0.01)
y = np.sin(np.pi*x)
self.axes.plot(x,y)
def changeAxes(self, min, max):
self.axes.set_ylim(float(min),float(max))
self.canvas.draw()
class BottomPanel(wx.Panel):
def __init__(self,parent, top):
wx.Panel.__init__(self, parent = parent)
#wx.Button(self,wx.ID_ANY, label="Button 2")
#self.SetBackgroundColour('Blue')
self.graph = top
self.togglebuttonStart = wx.ToggleButton(self,wx.ID_ANY,label="Start", pos=(10,10))
self.togglebuttonStart.Bind(wx.EVT_TOGGLEBUTTON, self.OnStartClick)
labelChannels = wx.StaticText(self, wx.ID_ANY, "Analog Inputs", pos=(200, 10))
self.cbl0 = wx.CheckBox(self,wx.ID_ANY, "A0", pos=(200, 30))
self.cbl1 = wx.CheckBox(self, wx.ID_ANY, "A1", pos=(200, 45))
self.cbl2 = wx.CheckBox(self, wx.ID_ANY, "A2", pos=(200, 60))
self.Bind(wx.EVT_CHECKBOX, self.OnChecked)
self.textboxSampleTime = wx.TextCtrl(self,wx.ID_ANY, "1000", pos=(200,115), size=(50,-1))
self.ButtonSend = wx.Button(self,wx.ID_ANY, "Send", pos=(255,115), size=(50,-1))
self.ButtonSend.Bind(wx.EVT_BUTTON, self.OnSend)
# A0 limit Values
labelMinY0 = wx.StaticText(self,wx.ID_ANY,"A0 Min Y", pos=(400,10))
self.textboxMinYAxis0 = wx.TextCtrl(self,wx.ID_ANY, "0", pos=(400,30))
labelMaxY0 = wx.StaticText(self, wx.ID_ANY, "A0 Max Y", pos=(400, 55))
self.textboxMaxYAxis0 = wx.TextCtrl(self, wx.ID_ANY, "1024", pos=(400, 75))
self.buttonRange0 = wx.Button(self, wx.ID_ANY, "Set Y0 Axis", pos=(400, 115))
self.buttonRange0.Bind(wx.EVT_BUTTON, self.SetButtonRange0)
# A1 limit Values
labelMinY1 = wx.StaticText(self, wx.ID_ANY, "A1 Min Y", pos=(530, 10))
self.textboxMinYAxis1 = wx.TextCtrl(self, wx.ID_ANY, "0", pos=(530, 30))
labelMaxY1 = wx.StaticText(self, wx.ID_ANY, "A1 Max Y", pos=(530, 55))
self.textboxMaxYAxis1 = wx.TextCtrl(self, wx.ID_ANY, "1024", pos=(530, 75))
self.buttonRange1 = wx.Button(self, wx.ID_ANY, "Set Y1 Axis", pos=(530, 115))
self.buttonRange1.Bind(wx.EVT_BUTTON, self.SetButtonRange1)
# A2 limit Values
labelMinY2 = wx.StaticText(self, wx.ID_ANY, "A2 Min Y", pos=(650, 10))
self.textboxMinYAxis2 = wx.TextCtrl(self, wx.ID_ANY, "0", pos=(650, 30))
labelMaxY2 = wx.StaticText(self, wx.ID_ANY, "A2 Max Y", pos=(650, 55))
self.textboxMaxYAxis2 = wx.TextCtrl(self, wx.ID_ANY, "1024", pos=(650, 75))
self.buttonRange2 = wx.Button(self, wx.ID_ANY, "Set Y2 Axis", pos=(650, 115))
self.buttonRange2.Bind(wx.EVT_BUTTON, self.SetButtonRange2)
def SetButtonRange0(self, event):
#print("Axis Button Clicked")
min = self.textboxMinYAxis0.GetValue()
max = self.textboxMaxYAxis0.GetValue()
print("(%s, %s)"% (min, max))
self.graph.changeAxes(min,max); # How to add it to Single Y-axis label?
def SetButtonRange1(self, event):
# print("Axis Button Clicked")
min = self.textboxMinYAxis1.GetValue()
max = self.textboxMaxYAxis1.GetValue()
print("(%s, %s)" % (min, max))
self.graph.changeAxes(min, max); # How to add it to Single Y-axis label?
def SetButtonRange2(self, event):
# print("Axis Button Clicked")
min = self.textboxMinYAxis2.GetValue()
max = self.textboxMaxYAxis2.GetValue()
print("(%s, %s)" % (min, max))
How to add it to Single Y-axis label?
self.graph.changeAxes(min, max);
def OnSend(self,event):
val = self.textboxSampleTime.GetValue()
print(val)
def OnChecked(self,event):
cb = event.GetEventObject()
print("%s is clicked" %(cb.GetLabel()))
def OnStartClick(self,event):
val = self.togglebuttonStart.GetValue()
if(val == True):
self.togglebuttonStart.SetLabel("Stop")
self.togglebuttonStart.SetBackgroundColour("red")
else:
self.togglebuttonStart.SetLabel("Start")
self.togglebuttonStart.SetBackgroundColour("green")
class Main(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None, title="App v0", size=(600,600))
splitter = wx.SplitterWindow(self)
top = TopPanel(splitter)
#bottom = BottomPanel(splitter)
bottom = BottomPanel(splitter,top)
splitter.SplitHorizontally(top, bottom)
splitter.SetMinimumPaneSize(300)
top.draw()
if __name__ == '__main__':
app = wx.App()
frame = Main()
frame.Show()
app.MainLoop()
The codes are done with WxPython and matplotlib. The top panel is for plotting line graph and bottom is for changing Y limits.
Image:Chart with multiple input limits in single Y axis
** Like this
I'm using wxpython to create a GUI.
The idea is that whenever I select a row, something will happen on notebook1 and notebook 2, and different tabs will appear with different related information.
However, when I bind an event when selecting a row, weird beird black squares appear on the tab titles. What's wrong?
import wx
import threading
from time import sleep
class VAR():
def __init__(self):
self.result_row = ''
var = VAR()
class TabOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the first tab", (20, 20))
class TabTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the second tab", (20, 20))
class GUI(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(1000, 1000), style=wx.DEFAULT_FRAME_STYLE &
~wx.MAXIMIZE_BOX ^ wx.RESIZE_BORDER, pos=(100, 0))
self.panel = wx.Panel(self)
self.hsizer = wx.BoxSizer(wx.VERTICAL)
first_panel = wx.Panel(self.panel, size=(1000, 420))
self.hsizer.Add(first_panel, 1)
self.second_panel = wx.Panel(self.panel, size=(1000, 600))
self.notebook1 = wx.Notebook(self.second_panel, size=(1000, 230))
self.notebook2 = wx.Notebook(self.second_panel, size=(1000, 400))
self.hsizer.Add(self.second_panel, 1)
self.second_panel_sizer = wx.BoxSizer(wx.VERTICAL)
self.second_panel_sizer.Add(self.notebook1, 1, wx.EXPAND)
self.second_panel_sizer.Add(self.notebook2, 2, wx.EXPAND)
self.second_panel.SetSizerAndFit(self.second_panel_sizer)
self.panel.SetSizerAndFit(self.hsizer)
var.result_row = wx.ListCtrl(
first_panel, -1, style=wx.LC_REPORT, size=(980, 245), pos=(0, 175))
var.result_row.InsertColumn(0, "No.")
var.result_row.InsertColumn(1, "2 ")
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.SelectRow, var.result_row)
def SelectRow(self, event):
while (self.notebook1.GetPageCount()):
self.notebook1.DeletePage(0)
while (self.notebook2.GetPageCount()):
self.notebook2.DeletePage(0)
tab1 = TabOne(self.notebook1)
self.notebook1.AddPage(tab1, "Tab 1")
sizer = wx.BoxSizer()
sizer.Add(self.notebook1, 1, wx.EXPAND)
self.second_panel.SetSizer(sizer)
tab2 = TabTwo(self.notebook2)
self.notebook2.AddPage(tab2, "Tab 2")
sizer = wx.BoxSizer()
sizer.Add(self.notebook2, 1, wx.EXPAND)
self.second_panel.SetSizer(sizer)
def InfiniteProcess():
for i in range(100):
sleep(0.1)
var.result_row.Append(str(i))
finish = False
a = threading.Thread(target=InfiniteProcess)
a.setDaemon(1)
a.start()
app = wx.App()
frame = GUI(None, -1, "a")
frame.Show()
app.MainLoop()
sample
I'm making an app that plots a figure after some processing. This is done after the user has introduced some values and pushes a button. However I don't get the figure plotted. Below there is a simplified code. This works fine if I plot directly the values of t and s, but not if it is done after pushing the button. What am I missing? Is there another better way to do so?
from numpy import arange, sin, pi
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 wx
class Input_Panel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Input variables
self.button = wx.Button(self, label="Go")
# Set sizer for the panel content
self.sizer = wx.GridBagSizer(1, 1)
self.sizer.Add(self.button, (1, 2), (3, 6), flag=wx.EXPAND)
self.SetSizer(self.sizer)
class Output_Panel_Var(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Output variables
self.tittle = wx.StaticText(self, label="OUTPUTS:")
self.font = wx.Font(12, wx.DECORATIVE, wx.BOLD, wx.NORMAL)
self.tittle.SetFont(self.font)
self.lblt = wx.StaticText(self, label="t:")
self.resultt = wx.StaticText(self, label="", size=(100, -1))
self.lbls = wx.StaticText(self, label="s:")
self.results = wx.StaticText(self, label="", size=(100, -1))
# Set sizer for the panel content
self.sizer = wx.GridBagSizer(2, 2)
self.sizer.Add(self.tittle, (1, 3))
self.sizer.Add(self.lblt, (3, 1))
self.sizer.Add(self.resultt, (3, 2))
self.sizer.Add(self.lbls, (4, 1))
self.sizer.Add(self.results, (4, 2))
self.SetSizer(self.sizer)
class Output_Panel_Fig(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
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)
def draw(self,t,s):
self.axes.plot(t, s)
class Main_Window(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title = title, pos = (0, 0), size = wx.DisplaySize())
# Set variable panels
self.main_splitter = wx.SplitterWindow(self)
self.out_splitter = wx.SplitterWindow(self.main_splitter)
self.inputpanel = Input_Panel(self.main_splitter)
self.inputpanel.SetBackgroundColour('#c4c4ff')
self.outputpanelvar = Output_Panel_Var(self.out_splitter)
self.outputpanelvar.SetBackgroundColour('#c2f1f5')
self.outputpanelfig = Output_Panel_Fig(self.out_splitter)
self.main_splitter.SplitVertically(self.inputpanel, self.out_splitter)
self.out_splitter.SplitHorizontally(self.outputpanelvar, self.outputpanelfig)
# Set event handlers
self.inputpanel.button.Bind(wx.EVT_BUTTON, self.OnButton)
def OnButton(self, e):
t = arange(0.0, 1.0, 0.01)
s = sin(2 * pi * t)
#self.outputpanelvar.resultt.SetLabel('%.5f' % t)
#self.outputpanelvar.resultt.SetLabel('%.5f' % s)
self.outputpanelfig.draw(t,s)
def main():
app = wx.App(False)
frame = Main_Window(None, "T-Matrix Codes GUI")
frame.Show()
app.MainLoop()
if __name__ == "__main__" :
main()
I think you are missing a redraw of the canvas. It is not enough to do a new plot but a refresh of the drawing pane must be done! Add a self.canvas.draw() after your plot command in the draw method of the Output_Panel_Fig this should help.
import ...
class Input_Panel(wx.Panel):
def __init__(self, parent):
...
class Output_Panel_Var(wx.Panel):
def __init__(self, parent):
...
class Output_Panel_Fig(wx.Panel):
def __init__(self, parent):
...
def draw(self,t,s):
self.axes.plot(t, s)
self.canvas.draw()
class Main_Window(wx.Frame):
def __init__(self, parent, title):
...
def OnButton(self, e):
...
def main():
...
if __name__ == "__main__" :
main()
At the moment I have a scatter graph which I can zoom in, move around etc.
What I also want to do is be able to select a certain number of points on the graph, then store the selected points in an array.
Is there any special function in matplotlib I can use?
Any help will be greatly appreciated
My code
import os
import wx
import numpy as nump
import matplotlib
matplotlib.use('WXAgg')
import matplotlib.figure as fg
import matplotlib.backends.backend_wxagg as wxagg
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Title')
self.create_main_panel()
self.draw_figure()
def create_main_panel(self):
self.panel = wx.Panel(self)
self.dpi = 100
self.fig = fg.Figure((5.0, 4.0), dpi=self.dpi)
self.canvas = wxagg.FigureCanvasWxAgg(self.panel, -1, self.fig)
self.axes = self.fig.add_subplot(111)
self.toolbar = wxagg.NavigationToolbar2WxAgg(self.canvas)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.vbox.AddSpacer(25)
self.vbox.Add(self.toolbar, 0, wx.EXPAND)
self.panel.SetSizer(self.vbox)
self.vbox.Fit(self)
def draw_figure(self):
self.axes.clear()
x, y = [2,3,4,5]
self.axes.scatter(x, y)
self.canvas.draw()
def on_exit(self, event):
self.Destroy()
if __name__ == '__main__':
app = wx.PySimpleApp()
app.frame = MyFrame()
app.frame.Show()
app.MainLoop()
The code below provides a possible solution. The basic method may be summarized as follows:
One attaches a handler for pick_event that keeps appending the picked data indices to a list self._picked_indices.
A key_press_event handler clears the self._picked_indices list whenever the user presses the escape key.
The method MyFrame.picked_points returns a list of coordinates of currently selected points. This method returns None if no points have been selected yet (you can modify it to return an empty list in this case if that is more convenient).
This way you can keep selecting points by clicking on them. But if you want to start over again, just press escape and start picking again.
#! /usr/bin/env python
import os
import wx
import numpy as nump
import matplotlib
matplotlib.use('WXAgg')
import matplotlib.figure as fg
import matplotlib.backends.backend_wxagg as wxagg
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Title')
self.create_main_panel()
self.draw_figure()
self._is_pick_started = False
self._picked_indices = None
def create_main_panel(self):
self.panel = wx.Panel(self)
self.dpi = 100
self.fig = fg.Figure((5.0, 4.0), dpi=self.dpi)
self.canvas = wxagg.FigureCanvasWxAgg(self.panel, -1, self.fig)
self.axes = self.fig.add_subplot(111)
self.toolbar = wxagg.NavigationToolbar2WxAgg(self.canvas)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.vbox.AddSpacer(25)
self.vbox.Add(self.toolbar, 0, wx.EXPAND)
self.panel.SetSizer(self.vbox)
self.vbox.Fit(self)
self.fig.canvas.mpl_connect('pick_event', self.on_pick)
self.fig.canvas.mpl_connect('key_press_event', self.on_key)
def draw_figure(self):
self.axes.clear()
self._x_data, self._y_data = [[2,3], [4,5]]
self.axes.scatter(self._x_data, self._y_data, picker=5)
self.canvas.draw()
def on_exit(self, event):
self.Destroy()
def picked_points(self):
if self._picked_indices is None:
return None
else:
return [ [self._x_data[i], self._y_data[i]]
for i in self._picked_indices ]
def on_pick(self, event):
if not self._is_pick_started:
self._picked_indices = []
self._is_pick_started = True
for index in event.ind:
if index not in self._picked_indices:
self._picked_indices.append(index)
print self.picked_points()
def on_key(self, event):
"""If the user presses the Escape key then stop picking points and
reset the list of picked points."""
if 'escape' == event.key:
self._is_pick_started = False
self._picked_indices = None
return
if __name__ == '__main__':
app = wx.PySimpleApp()
app.frame = MyFrame()
app.frame.Show()
app.MainLoop()
im having a little issue with NoteBook switching. When I switch notebook tabs, I will need to resize to make the wigdets display properly. I tried using self.Refresh() but that does not seem to do anything. If you have trouble understanding me, please run the following code, then switch tabs and resize, you will notice that there is problems, displaying things correctly. I do not know if this is a problem with wxPython but I think it is with my code.
IMAGE_NAME = []
IMAGE_DATA = []
IMAGEMORE_NAME=[]
IMAGEMORE_DATA=[]
import sys
import wx
def deletepic(self):
try:
self.parent.bitmap.Destroy()
except:
print sys.exc_info()
def sendnewpic(self):
if self.parent.bitmap: deletepic(self)
if IMAGE_DATA[self.image_listsel] != '':
try:
print IMAGE_DATA[self.image_listsel]
bmp = wx.Image(IMAGE_DATA[self.image_listsel], wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.parent.scroll_img.SetScrollbars(1, 1, bmp.GetWidth(), bmp.GetHeight())
self.parent.bitmap = wx.StaticBitmap(self.parent.scroll_img, -1, bmp, (0, 0))
self.parent.Refresh()
except:
pass
def areachange(self, pg):
print pg
try:
if IMAGE_DATA[self.image_listsel] == '':
deletepic(self)
except:
pass
if pg == "Regular Pictures":
self.images_area.Show()
self.scroll_img.Show()
self.btnTwo.Show()
else:
self.images_area.Hide()
self.scroll_img.Hide()
self.btnTwo.Hide()
if pg == "More Pictures":
self.images_area.Show()
self.scroll_img.Show()
self.imageboxersiz.Show()
else:
self.imageboxersiz.Hide()
self.Refresh()
class imageTab(wx.Panel):
def __init__(self, parent, grandparent):
wx.Panel.__init__(self, parent)
self.parent = grandparent
self.image_listsel = 0
self.listBox = wx.ListBox(self, size=(200, -1), choices=IMAGE_NAME, style=wx.LB_SINGLE)
self.sizer = wx.BoxSizer(wx.VERTICAL)
btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
self.sizerMain = wx.BoxSizer()
self.listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.reName)
self.listBox.Bind(wx.EVT_LISTBOX, self.imagesel)
btn = wx.Button(self, label="Create New",size=(200, 40))
btnTwo = wx.Button(self, label="Test 2",size=(200, 40))
btn.Bind(wx.EVT_BUTTON, self.newAddImage)
self.sizer.Add(self.listBox, proportion=1, flag=wx.TOP | wx.EXPAND | wx.LEFT, border=5)
btnSizer.Add(btn, 0, wx.ALL, 5)
btnSizer.Add(btnTwo, 0, wx.ALL, 5)
self.sizer.Add(btnSizer)
self.sizerMain.Add(self.sizer, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=0)
self.SetSizer(self.sizerMain)
def imagesel(self, evt):
self.image_listsel = self.listBox.GetSelection()
sendnewpic(self)
def newAddImage(self, evt):
IMAGE_NAME.append('hi')
IMAGE_DATA.append('')
self.listBox.Set(IMAGE_NAME)
self.listBox.SetSelection(len(IMAGE_NAME)-1)
self.imagesel(None) #making it a selected image, globally
def reName(self,parent):
sel = self.listBox.GetSelection()
text = self.listBox.GetString(sel)
renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
if renamed != '':
IMAGE_NAME.pop(sel)
IMAGE_NAME.insert(sel,renamed)
self.listBox.Set(IMAGE_NAME)
self.listBox.SetSelection(sel)
class objectTab(wx.Panel):
def __init__(self, parent, grandparent):
wx.Panel.__init__(self, parent)
self.parent = grandparent
self.image_listsel = 0
self.listBox = wx.ListBox(self, size=(200, -1), choices=IMAGEMORE_NAME, style=wx.LB_SINGLE)
self.sizer = wx.BoxSizer(wx.VERTICAL)
btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
self.sizerMain = wx.BoxSizer()
self.listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.reName)
self.listBox.Bind(wx.EVT_LISTBOX, self.imagesel)
btn = wx.Button(self, label="Create New",size=(200, 40))
btnTwo = wx.Button(self, label="Test 2",size=(200, 40))
btn.Bind(wx.EVT_BUTTON, self.newAddImage)
self.sizer.Add(self.listBox, proportion=1, flag=wx.TOP | wx.EXPAND | wx.LEFT, border=5)
btnSizer.Add(btn, 0, wx.ALL, 5)
btnSizer.Add(btnTwo, 0, wx.ALL, 5)
self.sizer.Add(btnSizer)
self.sizerMain.Add(self.sizer, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=0)
self.SetSizer(self.sizerMain)
def imagesel(self, evt):
self.image_listsel = self.listBox.GetSelection()
def newAddImage(self, evt):
IMAGEMORE_NAME.append('New image')
IMAGEMORE_DATA.append('')
self.listBox.Set(IMAGEMORE_NAME)
self.listBox.SetSelection(len(IMAGEMORE_NAME)-1)
self.imagesel(None) #making it a selected image, globally
def reName(self,parent):
sel = self.listBox.GetSelection()
text = self.listBox.GetString(sel)
renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
if renamed != '':
IMAGEMORE_NAME.pop(sel)
IMAGEMORE_NAME.insert(sel,renamed)
self.listBox.Set(IMAGEMORE_NAME)
self.listBox.SetSelection(sel)
class MyPanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
self.notebook = wx.Notebook(self, size=(225, -1))
self.tab_images = imageTab(self.notebook, self)
self.notebook.AddPage(self.tab_images, "Regular Pictures", select=True)
self.tab_imagesmore = objectTab(self.notebook, self)
self.notebook.AddPage(self.tab_imagesmore, "More Pictures")
self.scroll_img = wx.ScrolledWindow(self, -1)
self.scroll_img.SetScrollbars(1, 1, 600, 400)
self.images_area = wx.StaticBox(self, -1, '')
self.sizerBox = wx.StaticBoxSizer(self.images_area, wx.HORIZONTAL)
self.sizerBox2 = wx.BoxSizer()
self.sizerBox.Add(self.scroll_img, 1, wx.EXPAND|wx.ALL, 10)
self.sizerBox2.Add(self.sizerBox, 1, wx.EXPAND|wx.ALL, 10)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.notebook, proportion=0, flag=wx.EXPAND)
btnSizer = wx.BoxSizer(wx.VERTICAL) #change to horizontal for side by side
self.btnTwo = wx.Button(self, label="Load File", size=(200, 40))
self.bmp = None
self.bitmap = None
self.imageboxersiz=wx.ComboBox(self, -1, "None Selected!",(0, 0), (190,20),IMAGE_NAME, wx.CB_DROPDOWN)
btnSizer.Add(self.imageboxersiz, 0, wx.TOP, 15)
btnSizer.Add(self.btnTwo, 0, wx.TOP, 15)
self.sizerBox2.Add(btnSizer)
#
self.sizer.Add(self.sizerBox2, proportion=1, flag=wx.EXPAND)
self.SetSizer(self.sizer)
self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
areachange(self, self.notebook.GetPageText(0))
def OnClickTop(self, event):
self.scroll_img.Scroll(600, 400)
def OnClickBottom(self, event):
self.scroll_img.Scroll(1, 1)
def OnPageChanged(self, event):
new = event.GetSelection()
areachange(self, self.notebook.GetPageText(new))
event.Skip()
def OnPageChanging(self, event):
event.Skip()
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = MyPanel(self)
self.Show()
app = wx.App(False)
win = MainWindow(None, size=(600, 400))
app.MainLoop()
Thank you very much.
Just change the self.Refresh() to self.Layout(). Worked for me on Windows 7 anyway.