Return value from wxPython frame

Can someone show me how I can return a value from a wxPython frame? When clicks on usage close, I display an error message asking him a question. I would like to return the return code of this message dialog to my calling function.

thanks

+7
python wxpython
source share
8 answers

Since wxFrame has events that are handled by the app.MainLoop () function, the only way to get the wx.Frame () return value is to capture the event.

The standard practice of handling events usually occurs inside a class that comes from wx.Window itself (for example, Frame, Panel, etc.). Since you want the wx.Frame appearance code to receive the information gathered by processing the OnClose () event, the best way to do this is to register an event handler for your frame.

The documentation for wx.Window :: PushEventHandler is probably the best resource, and even the wxpython wiki contains a great article on how to do this. Inside the article, they register a custom handler that is an instance of "MouseDownTracker". Instead of creating an instance inside the PushEventHandler call, you must create it before the call to save the handle to the derived EventHandler class. That way, you can test your derived variables of the EventHandler class after the Frame has been destroyed or even let this derived class do special things for you.

Here is an adaptation of this code from a python wx file (admittedly a bit confusing due to the requirement of processing the results of a custom event using the "call" function):

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() 
+5
source share

You can get the result of pressing the OK, CANCEL buttons from the Dialog ShowModal method.
This dialog is an instance of one of the wxPython dialog classes:

 result = dialog.ShowModal() if result == wx.ID_OK: print "OK" else: print "Cancel" dialog.Destroy() 
+2
source share

I wanted to do the same in order to have a graphical β€œbuilder” that I could run from a console application. Here is how I did it.

 # 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 

Then from the console application, I would run this code.

 # Usage.py import Fruit picker = Fruit.Picker('Pick a Fruit') fruit = picker.pick() print 'User picked %s' % fruit 
+1
source share

user1594322's answer works, but it requires you to put all your controls in your wx.App instead of wx.Frame. This will complicate the process of recycling code.

My solution involves defining the variable "PassBack" when defining the init function. (similar to the variable "parent", but it is usually used when initializing wx.Frame)

From my code:

 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 

and for the frame class:

 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 

and somewhere at runtime MyFrame

 self.passBack.outputFromFrame = "Hello" 

so everything to get a string from the application

 app = MyApp() val = app.getOutput() #Proceed to do something with val 
+1
source share

A few years late for the initial question, but when I myself look for the answer to this question, I came across a built-in method to get the return value from the modal, without delving into any ordinary fun of events. I realized that I would send it in case someone needs it.

This is just this guy right here:

wxDialog :: EndModal void EndModal ( int retCode )

Ends the modal dialog by passing the value returned from * wxDialog :: call ShowModal. *

Using the above, you can return everything you want from the dialog box.

A usage example will subclass wx.Dialog , and then put the EndModal function in button handlers.

 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() 

(Note: I just quickly hit this code, did not test sizers)

As you can see, all you have to do is call EndModal from the button event to return the value for what generated the dialog.

+1
source share

Mark this answer on comp.lang.python: Linkie

0
source share

I do not think wxFrame can return a value since it is not modal. If you do not need to use wxFrame, then a modal dialog may work for you. If you really need a frame, I would consider using a custom event.

It will look something like this: (1) The user clicks to close wxFrame (2) You redefine OnClose (or something like that) to open a dialog box to ask the user a question (3) Create and publish a custom event (4 ) Close wxFrame (5) Some other codes handle your custom event

0
source share

I think I had the same problem as you. Instead of making this popup, I made a dialog instead. I created my own dialog, inheriting wx.dialog instead of wx.frame. Then you can use the code that joaquin posted above. You check the return value of the dialog box to see what was entered. This can be done by storing the value of textctrl when the user clicks ok on the local variable. Then, before it is destroyed, you somehow get this value.

The user dialogue on this site really helped me. http://zetcode.com/wxpython/dialogs/

0
source share

All Articles