有人能告诉我如何从wxPython Frame返回一个值吗?当用户点击关闭时,我会弹出一个消息对话框,询问他一个问题。我想将此消息对话框的返回代码返回给我的调用函数。
由于
答案 0 :(得分:5)
因为wxFrame具有通过app.MainLoop()函数处理的事件,所以获取wx.Frame()的返回值的唯一方法是通过捕获事件。
处理事件的标准做法通常来自wx.Window本身派生的类(例如,Frame,Panel等)。由于您希望wx.Frame外部的代码接收在处理OnClose()事件时收集的信息,因此最好的方法是为您的帧注册事件处理程序。
wx.Window :: PushEventHandler的文档可能是最好的资源,甚至wxpython wiki都有关于如何执行此操作的精彩文章。在文章中,他们注册了一个自定义处理程序,它是“MouseDownTracker”的一个实例。您不希望在PushEventHandler调用中进行实例化,而是希望在调用之前对其进行实例化,以便您可以保留EventHandler派生类的句柄。这样,你可以在Frame被销毁之后检查派生的EventHandler类变量,或者甚至允许派生类为你做特殊的事情。
以下是来自wx python wiki的代码的改编(由于需要使用“调用”函数处理自定义事件的结果,因此有点令人费解):
import sys
import wx
import wx.lib.newevent
(MyCustomEvent, EVT_CUSTOM) = wx.lib.newevent.NewEvent()
class CustomEventTracker(wx.EvtHandler):
def __init__(self, log, processingCodeFunctionHandle):
wx.EvtHandler.__init__(self)
self.processingCodeFunctionHandle = processingCodeFunctionHandle
self.log = log
EVT_CUSTOM(self, self.MyCustomEventHandler)
def MyCustomEventHandler(self, evt):
self.log.write(evt.resultOfDialog + '\n')
self.processingCodeFunctionHandle(evt.resultOfDialog)
evt.Skip()
class MyPanel2(wx.Panel):
def __init__(self, parent, log):
wx.Panel.__init__(self, parent)
self.log = log
def OnResults(self, resultData):
self.log.write("Result data gathered: %s" % resultData)
class MyFrame(wx.Frame):
def __init__(self, parent, ID = -1, title = "", pos = wx.DefaultPosition,
size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, ID, title, pos, size, style)
self.panel = panel = wx.Panel(self, -1, style = wx.TAB_TRAVERSAL
| wx.CLIP_CHILDREN
| wx.FULL_REPAINT_ON_RESIZE)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add((25, 25))
row = wx.BoxSizer(wx.HORIZONTAL)
row.Add((25,1))
m_close = wx.Button(self.panel, wx.ID_CLOSE, "Close")
m_close.Bind(wx.EVT_BUTTON, self.OnClose)
row.Add(m_close, 0, wx.ALL, 10)
sizer.Add(row)
self.panel.SetSizer(sizer)
def OnClose(self, evt):
dlg = wx.MessageDialog(self,
"Do you really want to close this frame?",
"Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
result = dlg.ShowModal()
dlg.Destroy()
if result == wx.ID_CANCEL:
event = MyCustomEvent(resultOfDialog = "User Clicked CANCEL")
self.GetEventHandler().ProcessEvent(event)
else: # result == wx.ID_OK
event = MyCustomEvent(resultOfDialog = "User Clicked OK")
self.GetEventHandler().ProcessEvent(event)
self.Destroy()
app = wx.App(False)
f2 = wx.Frame(None, title="Frame 1 (for feedback)", size=(400, 350))
p2 = MyPanel2(f2, sys.stdout)
f2.Show()
eventTrackerHandle = CustomEventTracker(sys.stdout, p2.OnResults)
f1 = MyFrame(None, title="PushEventHandler Tester (deals with on close event)", size=(400, 350))
f1.PushEventHandler(eventTrackerHandle)
f1.Show()
app.MainLoop()
答案 1 :(得分:2)
您可以从Dialog ShowModal方法中获得单击“确定”,“取消”按钮的结果 给定对话框是其中一个wxPython Dialog类的实例:
result = dialog.ShowModal()
if result == wx.ID_OK:
print "OK"
else:
print "Cancel"
dialog.Destroy()
答案 2 :(得分:2)
对于最初的问题已经晚了几年,但是当我自己寻找这个问题的答案时,我偶然发现了一种从模态中获取返回值的内置方法,而不会弄乱任何自定义事件的乐趣。想我会发布在这里以防其他人需要它。
这就是这个人:
wxDialog :: EndModal void EndModal( int retCode )
结束模式对话框,传递要从返回的值 * wxDialog :: ShowModal调用。*
使用上述内容,您可以从对话框中返回任何内容。
示例用法是将wx.Dialog
子类化,然后将EndModal
函数放在按钮处理程序中。
class ProjectSettingsDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, None, -1, "Project Settings", size=(600,400))
sizer = wx.BoxSizer(wx.VERTICAL) #main sized
sizer.AddStretchSpacer(1)
msg = wx.StaticText(self, -1, label="This is a sample message")
sizer.Add(msg, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 15)
horizontal_sizer = wx.BoxSizer(wx.HORIZONTAL)
okButton = wx.Button(self, -1, 'OK')
self.Bind(wx.EVT_BUTTON, self.OnOK, okButton)
cancelBtn = wx.Button(self, -1, "Cancel")
self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelBtn)
horizontal_sizer.Add(okButton, 0, wx.ALIGN_LEFT)
horizontal_sizer.AddStretchSpacer(1)
horizontal_sizer.Add(cancelBtn, 0, wx.ALIGN_RIGHT)
sizer.Add(horizontal_sizer, 0)
sizer.AddStretchSpacer(1)
self.SetSizer(sizer)
def OnOK(self, event):
self.EndModal(wx.ID_OK) #returns numeric code to caller
self.Destroy()
def OnCancel(self, event):
self.EndModal(wx.ID_CANCEL) #returns numeric code to caller
self.Destroy()
(注意:我刚刚快速敲除了这段代码;没有测试大小调整器)
正如您所看到的,您需要做的就是从按钮事件中调用EndModal
以将值返回到生成对话框的任何内容。
答案 3 :(得分:1)
我想做同样的事情,拥有一个可以在控制台应用程序中运行的图形“选择器”。我就是这样做的。
# Fruit.py
import wx
class Picker (wx.App):
def __init__ (self, title, parent=None, size=(400,300)):
wx.App.__init__(self, False)
self.frame = wx.Frame(parent, title=title, size=size)
self.apple_button = wx.Button(self.frame, -1, "Apple", (0,0))
self.apple_button.Bind(wx.EVT_BUTTON, self.apple_button_click)
self.orange_button = wx.Button(self.frame, -1, "Orange", (0,100))
self.orange_button.Bind(wx.EVT_BUTTON, self.orange_button_click)
self.fruit = None
self.frame.Show(True)
def apple_button_click (self, event):
self.fruit = 'apple'
self.frame.Destroy()
def orange_button_click (self, event):
self.fruit = 'orange'
self.frame.Destroy()
def pick (self):
self.MainLoop()
return self.fruit
然后从控制台应用程序中,我将运行此代码。
# Usage.py
import Fruit
picker = Fruit.Picker('Pick a Fruit')
fruit = picker.pick()
print 'User picked %s' % fruit
答案 4 :(得分:1)
user1594322的答案有效,但它要求您将所有控件放在wx.App中,而不是wx.Frame。这将使代码更难回收。
我的解决方案涉及在定义 init 功能时定义“PassBack”变量。 (类似于“父”变量,但通常在启动wx.Frame时使用它)
从我的代码:
class MyApp(wx.App):
def __init__ (self, parent=None, size=(500,700)):
wx.App.__init__(self, False)
self.frame = MyFrame(parent, -1, passBack=self) #Pass this app in
self.outputFromFrame = "" #The output from my frame
def getOutput(self):
self.frame.Show()
self.MainLoop()
return self.outputFromFrame
和帧类:
class MyFrame(wx.Frame):
def __init__(self, parent, ID, passBack, title="My Frame"):
wx.Frame.__init__(self, parent, ID, title, size=(500, 700))
self.passBack = passBack #this will be used to pass back variables/objects
在执行MyFrame期间的某个地方
self.passBack.outputFromFrame = "Hello"
总而言之,从应用程序中获取字符串
app = MyApp()
val = app.getOutput()
#Proceed to do something with val
答案 5 :(得分:0)
在comp.lang.python上查看此答案:Linkie
答案 6 :(得分:0)
我认为wxFrame不能返回值,因为它不是模态的。如果您不需要使用wxFrame,那么模态对话框可能适合您。如果你真的需要一个框架,我会考虑使用自定义事件。
它会是这样的: (1)用户点击关闭wxFrame (2)您重写OnClose(或类似的东西)以弹出一个对话框,询问用户一个问题 (3)创建并发布自定义事件 (4)关闭wxFrame (5)其他一些代码处理您的自定义事件
答案 7 :(得分:0)
我想我和你有同样的问题。我没有将弹出窗口设为框架,而是将其设为对话框。我通过继承wx.dialog而不是wx.frame来创建自定义对话框。然后你可以使用joaquin上面发布的代码。您可以检查对话框的返回值以查看输入的内容。这可以通过在用户单击ok到本地变量时存储textctrl的值来完成。然后在它被摧毁之前,你会以某种方式得到这个价值。
这个网站的自定义对话框部分帮助了我。 http://zetcode.com/wxpython/dialogs/