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

私の理解が正しければ、1) SpinCtrl 内で Enter キーを押すか、2) [更新] ボタンを押した場合にのみ、SpinCtrl 値を使用してアプリの内部値を更新する必要があります。次のサンプルは、まさにそれを行います。

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 に答える