wxpython透鏡演示系統(二):初始化與參數調節

初始化與參數調節面板

這一節將繪製出如下圖所示的參數調節面板

在這裏插入圖片描述

對於上圖來說,BoxSizer佈局十分傻瓜,所以這裏主要有兩個方面需要注意,其一是optisource這兩個選項卡的實現,其二則是如何同時創建多個滾動條。

對於前者比較容易,無非是多用一個控件而已,即wx.NoteBook,使用方法乏善可陳,看代碼即可學會。

對於後者當然也可以很容易,只要無腦羅列即可,只不過對於五個不同的參數就意味着要新建五組滾動條,要就要新建五個控制函數,而這五個控制函數的功能幾乎是完全一樣的。顯然,這很愚蠢,所以我們採用瞭如下的辦法對代碼進行精簡。

def InitPanel(self):
    self.drawPanel = wx.Panel(self) #繪圖面板

    #########初始化paraBook
    paraBook = wx.Notebook(self,size=(300,-1))
    optiPanel = wx.Panel(paraBook)
    sourcePanel = wx.Panel(paraBook)
    paraBook.AddPage(optiPanel,'opti')
    paraBook.AddPage(sourcePanel,'source')

    ###需要初始化edge
    self.setEdge()

    ####################optiBox###################
    self.paraSliders = {}
    optiBox = wx.BoxSizer(wx.VERTICAL)
    for key in self.optiDict:
        self.paraSliders[key]=wx.Slider(
            optiPanel,minValue=1,maxValue=1000,size=(200,-1))
        self.paraSliders[key].Bind(wx.EVT_SCROLL,
            lambda evt,mark=key: self.OnSliderScroll(evt,mark))
        optiBox.Add(self.paraSliders[key],proportion=1,
            flag=wx.LEFT|wx.CENTER)
        optiBox.Add(wx.StaticText(optiPanel,size=(120,30),label=key,
            style=wx.ALIGN_RIGHT),proportion=1,
            flag=wx.ALIGN_CENTER, border=10)

    self.testFlag = wx.TextCtrl(
        optiPanel,size=(250,400),value='hellos',style=wx.TE_MULTILINE)
    optiBox.Add(self.testFlag,proportion=1,
        flag=wx.ALIGN_CENTER|wx.ALL|wx.ALIGN_RIGHT,border=0)

    optiPanel.SetSizer(optiBox)

    ####################sourceBox###################

    sourceBox = wx.BoxSizer(wx.VERTICAL)
    for key in self.sourceDict:
        self.paraSliders[key]=wx.Slider(
            sourcePanel,minValue=1,maxValue=1000,size=(200,-1))
        self.paraSliders[key].Bind(wx.EVT_SCROLL,
            lambda evt,mark=key: self.OnSliderScroll(evt,mark))
        sourceBox.Add(self.paraSliders[key],proportion=1,
            flag=wx.LEFT|wx.CENTER)
        sourceBox.Add(wx.StaticText(sourcePanel,size=(120,30),label=key,
            style=wx.ALIGN_RIGHT),proportion=1,
            flag=wx.ALIGN_CENTER, border=10)

    sourcePanel.SetSizer(sourceBox)

    mainBox = wx.BoxSizer()
    mainBox.Add(self.drawPanel,proportion=1,flag=wx.ALL|wx.EXPAND,border=10)
    mainBox.Add(paraBook,proportion=0,flag=wx.ALL|wx.EXPAND,border=10)

    self.SetSizer(mainBox)

def OnSliderScroll(self,evt,mark):
    paraArea = {'ySource':[-300,300],'xSource':[0,1000],
                'xPos':[0,1200],'Diameter':[0,500],
                'lFocal':[-1000,1000],'rFocal':[-1000,1000],
                'theta':[0,np.pi*2],'nOpti':[0.1,10]}
    pValue = self.paraSliders[mark].GetValue()
    pMin,pMax=paraArea[mark]
    if mark in self.optiDict:
        self.optiDict[mark] = pMin+(pMax-pMin)/1000*pValue
    elif mark in self.sourceDict:
        self.sourceDict[mark]=pMin+(pMax-pMin)/1000*pValue
    pStr = ''
    for key in self.optiDict:
        pStr += key+':'+str(self.optiDict[key])+'\n'

    self.setEdge()  #設置光學元件
    self.getRay()   #計算
    self.DrawPath() #繪圖

在上面的代碼中,關鍵之處在於使用了一個lambda表達式,使得事件函數可以傳入兩個參數,也就完成了一次性創建多個控件的目的。

分解來看,首先創建一個滾動條字典self.paraSliders = {},其鍵爲變量名稱,值則對應一個滾動條控件。實現方式爲

self.paraSliders[key]=wx.Slider(optiPanel,minValue=1,maxValue=1000,size=(200,-1))

然後對於每個滾動條,通過lambda綁定事件函數:

self.paraSliders[key].Bind(wx.EVT_SCROLL,lambda evt,mark=key: self.OnSliderScroll(evt,mark))

其中,wx.EVT_SCROLL爲滾動事件,lambda方法將evt和mark分別傳入到事件函數self.OnSliderScroll(evt,mark)中,其中mark的值即爲當前的鍵值。

最後,將滾動條壓入到Boxsizer中。

在其調用的OnSliderScroll中,首先定義參數字典,從而確定了不同滾動條的滾動範圍,通過mark值,使得參數和滾動條能夠一一對應。然後然後設置成員變量self.optiDict以及self.sourceDict

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章