1

我有一个计时器,它开始“采样”(现在只是一个随机编号)并绘制成图表 - 当按下“开始”时,计时器启动。这工作正常(绘图不是很好,但它工作),虽然我在这里的问题是引入一个“目标”值,以便样本值被改变 -尽管只有在通过输入键甚至更新按钮输入目标之后.

就目前而言,对目标 SpinCtrl 小部件所做的任何更改都是实时完成的,我不希望出现这种情况,我只想在 Enter 后更新

所以我明白我的问题与timersbinding events和 *wx.EVT_TEXT_ENTER*; 当计时器已经运行时,我捕获了多少个文本条目?

原谅我缺乏python知识。

我的代码:

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()
4

2 回答 2

1

如果我理解正确,您只想在以下情况下使用 SpinCtrl 值更新应用程序中的内部值:1) 按下 SpinCtrl 内部的 Enter 或 2) 按下更新按钮。以下示例可以做到这一点:

import wx

class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.panel = wx.Panel(self)
        self.spin = wx.SpinCtrl(self.panel)
        self.button = wx.Button(self.panel, label="Update")

        self.sizer = wx.BoxSizer()
        self.sizer.Add(self.spin)
        self.sizer.Add(self.button)

        self.panel.SetSizerAndFit(self.sizer)  
        self.Show()

        # Use EVT_CHAR_HOOK on Frame insted of wx.EVT_KEY_UP on SpinCtrl
        # to disable "on Enter go to next widget" functionality
        self.Bind(wx.EVT_CHAR_HOOK, self.OnKey) 
        self.button.Bind(wx.EVT_BUTTON, self.OnUpdate)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.timer.Start(500)

        self.value = 0

    def OnKey(self, e):
        if e.GetKeyCode() == wx.WXK_RETURN: # Is the key ENTER?
            self.value = self.spin.GetValue() # Read SpinCtrl and set internal value
        else: # Else let the event out of the handler
            e.Skip()

    def OnUpdate(self, e):
        self.value = self.spin.GetValue() # Read SpinCtrl and set internal value

    def OnTimer(self, e):
        # Show internal value
        print(self.value)

app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
于 2013-01-15T13:29:43.877 回答
0

如果您不想对旋转控件的每个操作做出反应,请不要绑定到它。相反,在 StartTimer() 函数中查询它的值。

于 2013-01-14T23:03:41.087 回答