2010-04-26 46 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