I have a timer that starts to ‘sample’ (just a random no. here for now) and plots to a graph – the timer is started when ‘Start’ is pressed. This works OK (plotting is not great but it works), though my issue here is to introduce a ‘Target’ value such that the sample value is altered by — though only after target is entered by the enter key or even a update button.
As it stands, any changes made to the target SpinCtrl widget are done so live and I don’t want this to be the case, I’d only like to update after Enter
So I understand my question relates to timers, binding events and *wx.EVT_TEXT_ENTER*; how many I capture a text entry whilst a timer is already running?
Forgive my lack of python knowledge.
My code:
print( "\n- Please Wait -- Importing Matplotlib and Related Modules...\n" )
import matplotlib
import numpy
import wx
import numpy as np
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 random
SamplingTime = 1# in ms
class GraphPanel( wx.Panel ) :
def __init__( self, parent, position ) :
wx.Panel.__init__( self, parent, pos=position, size=(800,320) )
# initialize matplotlib
self.figure = matplotlib.figure.Figure( None, facecolor="white" )
self.canvas = matplotlib.backends.backend_wxagg.FigureCanvasWxAgg( self, -1, self.figure )
self.axes = self.figure.add_subplot(111)
self.axes.grid(True, color="gray")
self.axes.set_xbound( (0,100) )
self.axes.set_ybound( (0,10) )
self.axes.set_xlabel( "Sample" )
self.axes.set_ylabel( "Data" )
self._SetSize()
self.Bind( wx.EVT_SIZE, self._SetSize )
self.Data = []
def updateData(self, value):
self.Data.append( value )
x = np.arange( len(self.Data) )
y = np.array(self.Data)
yMin = round(min(y)) + 2
yMax = round(max(y)) + 2
self.axes = self.figure.add_subplot(111)
self.axes.grid(True, color="gray")
self.axes.plot(x,y, "-k")
self.axes.set_ybound( (yMin,yMax) )
self.axes.set_xlabel( "Sample" )
self.axes.set_ylabel( "Data" )
self._SetSize()
self.Bind( wx.EVT_SIZE, self._SetSize )
self.canvas = FigureCanvas(self, -1, self.figure)
#-----------------------------------------------------------------------------------
def _SetSize( self, event=None ):
pixels = self.GetSize()
self.SetSize( pixels )
self.canvas.SetSize( pixels )
dpi = self.figure.get_dpi()
self.figure.set_size_inches( float( pixels[0] ) / dpi,float( pixels[1] ) / dpi )
#------------------------------------------------------------------------------------
############################################ Basic Frame ###################################################
class BasicFrame(wx.Frame):
def __init__(self, parent, title):
self.Data = 0
self.DataPrevious = 1
# split the screen
wx.Frame.__init__(self, parent, title="Data Collection", size=(1100,750))
self.sp = wx.SplitterWindow(self)
self.p1 = wx.Panel(self.sp, style = wx.SUNKEN_BORDER)
self.p2 = wx.Panel(self.sp, style = wx.SUNKEN_BORDER)
self.sp.SplitVertically(self.p1, self.p2, 940)
# graph
self.Graph = GraphPanel( self.p1, position=(20, 20) )
# define control input
wx.StaticBox(self.p2, -1, "System Control", pos=(5, 5), size=(120, 210))
wx.StaticText(self.p2, -1,"Target:", pos=(15, 100))
self.Target = wx.SpinCtrl(self.p2,-1,pos=(15,120), size=(80, 20), min=5, max=10)
self.Target.Bind(wx.EVT_BUTTON, self.StartSystem)
self.StartButton = wx.Button(self.p2, -1, "Start", pos=(20,230))
self.StartButton.Bind(wx.EVT_BUTTON, self.StartSystem)
self.PauseButton = wx.Button(self.p2, -1, "Pause", pos=(20,270))
self.PauseButton.Bind(wx.EVT_BUTTON, self.PauseSystem)
self.StopButton = wx.Button(self.p2, -1, "Stop", pos=(20,500))
self.StopButton.Bind(wx.EVT_BUTTON, self.StopSystem)
# set the timers
self.SampleTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.updateData, self.SampleTimer)
print( "Ready!\n" )
def sampleData(self):
Error = random.uniform(0, 0.2)
Target = self.Target.GetValue()
if( self.Data <= Target):
self.Data += self.DataPrevious*Error
elif( self.Data >= Target):
self.Data -= self.DataPrevious*Error
self.DataPrevious = self.Data
print( "Target Aim: "+str(self.Data) )
return self.Data
def updateData(self, event):
CurrentData = round(self.sampleData(),2) # obtain currnt data
self.Graph.updateData(CurrentData) # add data to graph
def StartSystem(self, event):
self.SampleTimer.Start(SamplingTime)
def PauseSystem(self, event):
self.SampleTimer.Stop()
def StopSystem(self, event):
self.SampleTimer.Stop()
self.Destroy()
app = wx.App(redirect=False)
frame = BasicFrame(None, -1)
frame.Show()
app.MainLoop()
If I understand correctly, you want to update the internal value in you app using the SpinCtrl value only if 1) Enter inside SpinCtrl is pressed or 2) Update button is pressed. The following sample would do just that: