2010-04-26 47 views
0

我剛剛開始使用wxPython的,這是我希望做什麼:的wxPython:如何處理事件綁定和show()正確

一)顯示框架(與面板裏面)和該面板上的按鈕。 b)當我按下按鈕時,會彈出一個對話框(我可以從中進行選擇)。 c)當我在對話框中按ok時,對話框應該消失(被破壞),但原始的Frame + Panel +按鈕仍然存在。 d)如果我再次按下該按鈕,對話框將重新出現。

我的代碼如下。 不幸的是,我得到了相反的效果。即,

a)選擇 - 對話框首先顯示(即,由於從不顯示TopLevelframe +按鈕,因此不點擊任何按鈕)。

b)當我在對話框上單擊確定,然後出現帶有按鈕的框架。 c)再次單擊按鈕不起作用(即,對話框不再顯示)。c)再次單擊按鈕不起作用(即,對話框不再顯示)。

我在做什麼錯?似乎只要框架被初始化(即使在調用.Show()之前),對話框也會自動初始化並顯示。

我與Python 2.6

============文件這樣使用Eclipse + Pydev的上的WindowsXP:MainFile.py ============ ===

import wx 
import MyDialog #This is implemented in another file: MyDialog.py 

class TopLevelFrame(wx.Frame): 

    def __init__(self,parent,id):  
     wx.Frame.__init__(self,parent,id,"Test",size=(300,200)) 
     panel=wx.Panel(self) 
     button=wx.Button(panel, label='Show Dialog', pos=(130,20), size=(60,20)) 

     # Bind EVENTS --> HANDLERS. 
     button.Bind(wx.EVT_BUTTON, MyDialog.start(self)) 


# Run the main loop to start program.   
if __name__=='__main__': 
    app=wx.PySimpleApp()  
    TopLevelFrame(parent=None, id=-1).Show() 
    app.MainLoop() 

============文件:MyDialog.py ===============

import wx 

def start(parent): 
    inputbox = wx.SingleChoiceDialog(None,'Choose Fruit', 'Selection Title', 
            ['apple','banana','orange','papaya']) 
    if inputbox.ShowModal()==wx.ID_OK: 
     answer = inputbox.GetStringSelection() 
     inputbox.Destroy() 

回答

2

有有很多方法可以做到這一點,但是要對您的代碼進行最少的更改,

更改def start(parent):

def start(parent, evt): 

,並更改button.Bind(wx.EVT_BUTTON, MyDialog.start(self))

button.Bind(wx.EVT_BUTTON, lambda evt: MyDialog.start(self, evt)) 

也就是說,在綁定的第二個參數必須是一個函數,它和事件,您需要創建對話框時該按鈕被點擊。 lambda使得這個函數也可以接受parent和evt(你也可以使用functools.partial for version> 2.5),然後當點擊按鈕時,start將被調用來創建對話框。

我不太清楚代碼中發生了什麼,但似乎您打電話給start並在您首次調用Bind時創建對話框,然後將返回值從開始None傳遞給Bind。

注1 更詳細地,在這裏使用的拉姆達的原因是,綁定應該有一個像Bind(event, handler)形式,其中event是wx.PyEventBinder,像wx.EVT_BUTTON和handler功能像foo(evt)其中evt是wx.Event或wx.CommandEvent。(這裏沒有遞歸,因爲你只是說發生什麼事情時該怎麼做,但那件事還沒有發生,所以事件還沒有被創建,當事件發生時,它將由一個wx .Event,這將對有關事件,像在鼠標是當它被點擊等)

注2 在我的答案信息,我試圖用最小的變化來回答你的問題,因爲我認爲這會最簡單。也許下面的代碼更清晰(也許它通常處理創建它們的小部件中最清晰的事件):

def start2(parent): 
    inputbox = wx.SingleChoiceDialog(parent,'Choose Fruit', 'Selection Title', 
            ['apple','banana','orange','papaya']) 
    if inputbox.ShowModal()==wx.ID_OK: 
     answer = inputbox.GetStringSelection() 
    inputbox.Destroy() 

class TopLevelFrame2(wx.Frame): 

    def __init__(self,parent,id):  
     wx.Frame.__init__(self,parent,id,"Test",size=(300,200)) 
     panel=wx.Panel(self) 
     button=wx.Button(panel, label='Show Dialog', pos=(130,20), size=(60,20)) 

     # Bind EVENTS --> HANDLERS. 
     button.Bind(wx.EVT_BUTTON, self.OnClick) 

    def OnClick(self, evt): 
     start2(self) 
+0

Tom,謝謝你的迴應。它可以稍作修改(即,在MyDialog.start中預先啓動(self,evt)...)。雖然我仍然不明白爲什麼這會起作用,爲什麼需要將這個lambda函數加入其中。對我來說似乎是這樣說的:當「按鈕」發出一個EVT_BUTTON事件時,然後執行由lambda定義的函數evt。但是evt只是MyDialog.start(self,evt)的執行[這不是某種遞歸,因爲evt被作爲參數傳遞給自己的定義?]。 – 2010-04-27 19:28:45

+0

我很高興聽到它的工作。我按照你的建議修正了包含MyDialog.start的代碼,並添加了一些評論來幫助澄清。 – tom10 2010-04-27 20:32:12

+0

再次感謝。我想我明白了(儘管我需要把這個理解用更復雜的例子來測試)。感謝你的幫助。 – 2010-04-28 13:04:53