wxPython and how to return text entry to main program?

T

Tyler

Hello All:

I am currently working on a project to create an FEM model for school.
I was thinking about using wxPython to gather the 12 input variables
from the user, then, after pressing the "Run" button, the GUI would
close, and the 12 input variables would then be available for the rest
of the program.

So far, what I have been able to do is mostly a reverse engineering
job to get the frame to look right and return the text variable to a
dialog box.

I have read about a "redirect" that could be used to send the values
to a file. But, then I would have to open the file and read in the
data from there. This seems crude and lacking elegance.

Any help on how to get the program to output the data back to the main
python program and close when I press submit? My apologies if this is
something of a simple question, but I have only started in on wxPython
about a week ago, and Python this term.

The codes I am using are below.

Any help (or suggested reading material) is greatly appreciated.

Cheers,

t.


MY MAIN PROGRAM

#!/usr/bin/env python
import femGUI
app = femGUI.MyApp(False)
dlg = femGUI.FemInput()
dlg.Destroy()
app.MainLoop()

# Then do something with inputs here....



THE FEMINPUT GUI CLASS

import wx

class FemInput(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Options Input Interface")
panel = wx.Panel(self)

# First create the controls

# Title
topLbl = wx.StaticText(panel, -1, "FEM 2D Basket Put Option
",size=(420,-1))
topLbl.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))

# S1 lower and upper bounds for grid
s1label = wx.StaticText(panel, -1, "S1 Low , S2 Low: ",
size=(220,-1))
self.s1lower = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2lower = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S2 lower and upper bounds for grid
s2label = wx.StaticText(panel, -1, "S1 High, S2 High: ",
size=(220,-1))
self.s1upper = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2upper = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S1 and S2 volatility
vlabel = wx.StaticText(panel, -1, "S1 Volatility, S2
Volatility: ", size=(220,-1))
self.v1vol = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.v2vol = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Risk free rate and correlation
prlabel = wx.StaticText(panel, -1, "Interest Rate,
Correlation: ", size=(220,-1))
self.risk = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.corr = wx.TextCtrl(panel, -1, "", size=(100,-1));


# Strike and Exercise Date
kTlabel = wx.StaticText(panel, -1, "Srike Price, Exercise
Date: ", size=(220,-1))
self.strike = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.finalT = wx.TextCtrl(panel, -1, "", size=(100,-1));

# deltaT and deltaX
dTXlabel = wx.StaticText(panel, -1, "delta T, delta X: ",
size=(220,-1))
self.deltaT = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.deltaX = wx.TextCtrl(panel, -1, "", size=(100,-1));


# Execute program
runBtn = wx.Button(panel, -1, "Run")
self.Bind(wx.EVT_BUTTON, self.OnSubmit, runBtn)

# Now do the layout.

# mainSizer is the top-level one that manages everything
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(topLbl, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel), 0,
wx.EXPAND|wx.TOP|wx.BOTTOM, 5)

# femSizer is a grid that holds all of the address info
femSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
femSizer.AddGrowableCol(1)

# S1 and S2 LOWER label
femSizer.Add(s1label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s1Sizer = wx.BoxSizer(wx.HORIZONTAL)
s1Sizer.Add(self.s1lower, 1)
s1Sizer.Add((10,10)) # some empty space
s1Sizer.Add(self.s2lower, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s1Sizer, 1, wx.EXPAND)


# S1 and S2 HIGH label
femSizer.Add(s2label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s2Sizer = wx.BoxSizer(wx.HORIZONTAL)
s2Sizer.Add(self.s1upper, 1)
s2Sizer.Add((10,10)) # some empty space
s2Sizer.Add(self.s2upper, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s2Sizer, 1, wx.EXPAND)


# Volatility label
femSizer.Add(vlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
volSizer = wx.BoxSizer(wx.HORIZONTAL)
volSizer.Add(self.v1vol, 1)
volSizer.Add((10,10)) # some empty space
volSizer.Add(self.v2vol, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(volSizer, 1, wx.EXPAND)


# Risk free Rate and corelation
femSizer.Add(prlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
rcSizer = wx.BoxSizer(wx.HORIZONTAL)
rcSizer.Add(self.risk, 1)
rcSizer.Add((10,10)) # some empty space
rcSizer.Add(self.corr, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(rcSizer, 1, wx.EXPAND)


# Strike and Exercise Date
femSizer.Add(kTlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
ktSizer = wx.BoxSizer(wx.HORIZONTAL)
ktSizer.Add(self.strike, 1)
ktSizer.Add((10,10)) # some empty space
ktSizer.Add(self.finalT, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(ktSizer, 1, wx.EXPAND)


# deltaT and deltaX
femSizer.Add(dTXlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
dtxSizer = wx.BoxSizer(wx.HORIZONTAL)
dtxSizer.Add(self.deltaT, 1)
dtxSizer.Add((10,10)) # some empty space
dtxSizer.Add(self.deltaX, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(dtxSizer, 1, wx.EXPAND)


# now add the femSizer to the mainSizer
mainSizer.Add(femSizer, 0, wx.EXPAND|wx.ALL, 10)

# The buttons sizer will put them in a row with resizeable
# gaps between and on either side of the buttons
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add((10,10)) # some empty space
btnSizer.Add(runBtn)
btnSizer.Add((10,10)) # some empty space
mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.BOTTOM, 10)

panel.SetSizer(mainSizer)

# Fit the frame to the needs of the sizer. The frame will
# automatically resize the panel as needed. Also prevent the
# frame from getting smaller than this size.
mainSizer.Fit(self)
mainSizer.SetSizeHints(self)

def OnSubmit(self, evt):
s1low = self.s1lower.GetValue()
s2low = self.s2lower.GetValue()
s1high = self.s1upper.GetValue()
s2high = self.s2upper.GetValue()
s1vol = self.v1vol.GetValue()
s2vol = self.v2vol.GetValue()
irate = self.risk.GetValue()
pcorr = self.corr.GetValue()
kprice = self.strike.GetValue()
totalT = self.finalT.GetValue()
delT = self.deltaT.GetValue()
delX = self.deltaX.GetValue()
wx.MessageBox('You chose: \n %s \n %s \n %s \n %s \
\n %s \n %s \n %s' %
(s1low,s2low,s1high,s2high,s1vol,s2vol,irate))
# I want to do something like this below....
# return s1low,s2low,s1high,s2high,s1vol,s2vol,irate



class MyApp(wx.App):

def OnInit(self):
frame = FemInput()
self.SetTopWindow(frame)
frame.Show()
return True


# Needed if called as a module
if __name__ == '__main__':
app = MyApp(False)
app.MainLoop()
 
K

kyosohma

Hello All:

I am currently working on a project to create an FEM model for school.
I was thinking about using wxPython to gather the 12 input variables
from the user, then, after pressing the "Run" button, the GUI would
close, and the 12 input variables would then be available for the rest
of the program.

So far, what I have been able to do is mostly a reverse engineering
job to get the frame to look right and return the text variable to a
dialog box.

I have read about a "redirect" that could be used to send the values
to a file. But, then I would have to open the file and read in the
data from there. This seems crude and lacking elegance.

Any help on how to get the program to output the data back to the main
python program and close when I press submit? My apologies if this is
something of a simple question, but I have only started in on wxPython
about a week ago, and Python this term.

The codes I am using are below.

Any help (or suggested reading material) is greatly appreciated.

Cheers,

t.

MY MAIN PROGRAM

#!/usr/bin/env python
import femGUI
app = femGUI.MyApp(False)
dlg = femGUI.FemInput()
dlg.Destroy()
app.MainLoop()

# Then do something with inputs here....

THE FEMINPUT GUI CLASS

import wx

class FemInput(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Options Input Interface")
panel = wx.Panel(self)

# First create the controls

# Title
topLbl = wx.StaticText(panel, -1, "FEM 2D Basket Put Option
",size=(420,-1))
topLbl.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))

# S1 lower and upper bounds for grid
s1label = wx.StaticText(panel, -1, "S1 Low , S2 Low: ",
size=(220,-1))
self.s1lower = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2lower = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S2 lower and upper bounds for grid
s2label = wx.StaticText(panel, -1, "S1 High, S2 High: ",
size=(220,-1))
self.s1upper = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2upper = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S1 and S2 volatility
vlabel = wx.StaticText(panel, -1, "S1 Volatility, S2
Volatility: ", size=(220,-1))
self.v1vol = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.v2vol = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Risk free rate and correlation
prlabel = wx.StaticText(panel, -1, "Interest Rate,
Correlation: ", size=(220,-1))
self.risk = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.corr = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Strike and Exercise Date
kTlabel = wx.StaticText(panel, -1, "Srike Price, Exercise
Date: ", size=(220,-1))
self.strike = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.finalT = wx.TextCtrl(panel, -1, "", size=(100,-1));

# deltaT and deltaX
dTXlabel = wx.StaticText(panel, -1, "delta T, delta X: ",
size=(220,-1))
self.deltaT = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.deltaX = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Execute program
runBtn = wx.Button(panel, -1, "Run")
self.Bind(wx.EVT_BUTTON, self.OnSubmit, runBtn)

# Now do the layout.

# mainSizer is the top-level one that manages everything
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(topLbl, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel), 0,
wx.EXPAND|wx.TOP|wx.BOTTOM, 5)

# femSizer is a grid that holds all of the address info
femSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
femSizer.AddGrowableCol(1)

# S1 and S2 LOWER label
femSizer.Add(s1label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s1Sizer = wx.BoxSizer(wx.HORIZONTAL)
s1Sizer.Add(self.s1lower, 1)
s1Sizer.Add((10,10)) # some empty space
s1Sizer.Add(self.s2lower, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s1Sizer, 1, wx.EXPAND)

# S1 and S2 HIGH label
femSizer.Add(s2label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s2Sizer = wx.BoxSizer(wx.HORIZONTAL)
s2Sizer.Add(self.s1upper, 1)
s2Sizer.Add((10,10)) # some empty space
s2Sizer.Add(self.s2upper, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s2Sizer, 1, wx.EXPAND)

# Volatility label
femSizer.Add(vlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
volSizer = wx.BoxSizer(wx.HORIZONTAL)
volSizer.Add(self.v1vol, 1)
volSizer.Add((10,10)) # some empty space
volSizer.Add(self.v2vol, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(volSizer, 1, wx.EXPAND)

# Risk free Rate and corelation
femSizer.Add(prlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
rcSizer = wx.BoxSizer(wx.HORIZONTAL)
rcSizer.Add(self.risk, 1)
rcSizer.Add((10,10)) # some empty space
rcSizer.Add(self.corr, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(rcSizer, 1, wx.EXPAND)

# Strike and Exercise Date
femSizer.Add(kTlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
ktSizer = wx.BoxSizer(wx.HORIZONTAL)
ktSizer.Add(self.strike, 1)
ktSizer.Add((10,10)) # some empty space
ktSizer.Add(self.finalT, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(ktSizer, 1, wx.EXPAND)

# deltaT and deltaX
femSizer.Add(dTXlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
dtxSizer = wx.BoxSizer(wx.HORIZONTAL)
dtxSizer.Add(self.deltaT, 1)
dtxSizer.Add((10,10)) # some empty space
dtxSizer.Add(self.deltaX, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(dtxSizer, 1, wx.EXPAND)

# now add the femSizer to the mainSizer
mainSizer.Add(femSizer, 0, wx.EXPAND|wx.ALL, 10)

# The buttons sizer will put them in a row with resizeable
# gaps between and on either side of the buttons
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add((10,10)) # some empty space
btnSizer.Add(runBtn)
btnSizer.Add((10,10)) # some empty space
mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.BOTTOM, 10)

panel.SetSizer(mainSizer)

# Fit the frame to the needs of the sizer. The frame will
# automatically resize the panel as needed. Also prevent the
# frame from getting smaller than this size.
mainSizer.Fit(self)
mainSizer.SetSizeHints(self)

def OnSubmit(self, evt):
s1low = self.s1lower.GetValue()
s2low = self.s2lower.GetValue()
s1high = self.s1upper.GetValue()
s2high = self.s2upper.GetValue()
s1vol = self.v1vol.GetValue()
s2vol = self.v2vol.GetValue()
irate = self.risk.GetValue()
pcorr = self.corr.GetValue()
kprice = self.strike.GetValue()
totalT = self.finalT.GetValue()
delT = self.deltaT.GetValue()
delX = self.deltaX.GetValue()
wx.MessageBox('You chose: \n %s \n %s \n %s \n %s \
\n %s \n %s \n %s' %
(s1low,s2low,s1high,s2high,s1vol,s2vol,irate))
# I want to do something like this below....
# return s1low,s2low,s1high,s2high,s1vol,s2vol,irate

class MyApp(wx.App):

def OnInit(self):
frame = FemInput()
self.SetTopWindow(frame)
frame.Show()
return True

# Needed if called as a module
if __name__ == '__main__':
app = MyApp(False)
app.MainLoop()

Right now I can't figure it out...but you can close it by sticking the
following code as the last line in the OnSubmit method:

self.Close(True)

Also, I highly recommend the wxPython in Action book by Robin Dunn.
You might also submit wxPython questions to the wxPython mailing group
at http://wxpython.org/maillist.php

Sorry I wasn't of more help.

Mike
 
S

Steve Holden

Tyler said:
Hello All:

I am currently working on a project to create an FEM model for school.
I was thinking about using wxPython to gather the 12 input variables
from the user, then, after pressing the "Run" button, the GUI would
close, and the 12 input variables would then be available for the rest
of the program.

So far, what I have been able to do is mostly a reverse engineering
job to get the frame to look right and return the text variable to a
dialog box.

I have read about a "redirect" that could be used to send the values
to a file. But, then I would have to open the file and read in the
data from there. This seems crude and lacking elegance.

Any help on how to get the program to output the data back to the main
python program and close when I press submit? My apologies if this is
something of a simple question, but I have only started in on wxPython
about a week ago, and Python this term.

The codes I am using are below.

Any help (or suggested reading material) is greatly appreciated.

There are two basic ways to do this. The first is to pass in something
that can store the values collected by the window. The second is to have
the values stored as attributes of the dialog and then extract them
after the user has finished interacting with the dialog but before you
Destroy() it.

See comments in the code. I have actually appended a version that works.
Maybe not the prettiest way to achieve what you want but it works.
Cheers,

t.


MY MAIN PROGRAM

#!/usr/bin/env python
import femGUI
app = femGUI.MyApp(False)
dlg = femGUI.FemInput()

So this is where you create your FemInput object. Here's where you could
pass it an object to receive the data values.

Assuming you want to store them as named attributes, about the simplest
thing you can use is an instance of some object. Here's an example in
the interactive interpreter:

So you could change that last line to

class Data: pass
data = Data()
app = femGUI.FemInput(data)

Of course this will mean edits below.
dlg.Destroy()

It seems a bit strange to be destroying your dialog before you've
actually called the MainLoop to start doing the windowing. I have to
take your word for it that this works ... it's almost certainly the
reason why you are having problems getting data out of the window. Or
maybe not.

I see when you run the program the window doesn't disappear when you
terminate the dialog. That's probably because (unless you want to do
more windowing stuff) you probably want to use ShowModal instead. This
will terminate the dialog and have it return to the caller when it's
finished.

Hmm, the whole structure's a little bit loopy ... and a FemInput window
has to be a dialog if you're going to use ShowModal() on it anyway ...
that's not good. It means the top-level frame has to Destroy() itself to
terminate the main loop and let you continue with the non-graphical portion.
app.MainLoop()

# Then do something with inputs here....
The problem at the moment is by the time you are ready to "do something
with the inputs" you have terminated your graphical environment - it is,
to coin a phrase, an *ex*-graphical environemnt, and it's too late to
poke about in it.

OK, here's a new main program for you. To make the "lines of
communication" a but more obvious it includes a definition of the MyApp
class.

#!/usr/bin/env python
import wx
import femGUI

class S: pass

s = S()

class MyApp(wx.App):
"You can throw away the MyApp in femGUI."

def OnInit(self):
myFrame = femGUI.FemInput(s) # passes storage object in
self.SetTopWindow(myFrame)
myFrame.Show()
return True

app = MyApp(False)
app.MainLoop()

print dir(storage)

The statement at the end is just to show you that the attributes exist.
From there you can do what you want.

Now it turns out you don't need to make that many modifications to your
class definition.
THE FEMINPUT GUI CLASS

import wx

class FemInput(wx.Frame):
def __init__(self):

The above line has to change because we have to accept, and store, a
reference to the storage object we provide in the FemInput constructor.

def __init__(self, storage):
self.storage = storage

Most if it is pretty much standard from here on, but keep reading.
wx.Frame.__init__(self, None, -1, "Options Input Interface")
panel = wx.Panel(self)

# First create the controls

# Title
topLbl = wx.StaticText(panel, -1, "FEM 2D Basket Put Option
",size=(420,-1))
topLbl.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))

# S1 lower and upper bounds for grid
s1label = wx.StaticText(panel, -1, "S1 Low , S2 Low: ",
size=(220,-1))
self.s1lower = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2lower = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S2 lower and upper bounds for grid
s2label = wx.StaticText(panel, -1, "S1 High, S2 High: ",
size=(220,-1))
self.s1upper = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2upper = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S1 and S2 volatility
vlabel = wx.StaticText(panel, -1, "S1 Volatility, S2
Volatility: ", size=(220,-1))
self.v1vol = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.v2vol = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Risk free rate and correlation
prlabel = wx.StaticText(panel, -1, "Interest Rate,
Correlation: ", size=(220,-1))
self.risk = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.corr = wx.TextCtrl(panel, -1, "", size=(100,-1));


# Strike and Exercise Date
kTlabel = wx.StaticText(panel, -1, "Srike Price, Exercise
Date: ", size=(220,-1))
self.strike = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.finalT = wx.TextCtrl(panel, -1, "", size=(100,-1));

# deltaT and deltaX
dTXlabel = wx.StaticText(panel, -1, "delta T, delta X: ",
size=(220,-1))
self.deltaT = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.deltaX = wx.TextCtrl(panel, -1, "", size=(100,-1));


# Execute program
runBtn = wx.Button(panel, -1, "Run")
self.Bind(wx.EVT_BUTTON, self.OnSubmit, runBtn)

# Now do the layout.

# mainSizer is the top-level one that manages everything
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(topLbl, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel), 0,
wx.EXPAND|wx.TOP|wx.BOTTOM, 5)

# femSizer is a grid that holds all of the address info
femSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
femSizer.AddGrowableCol(1)

# S1 and S2 LOWER label
femSizer.Add(s1label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s1Sizer = wx.BoxSizer(wx.HORIZONTAL)
s1Sizer.Add(self.s1lower, 1)
s1Sizer.Add((10,10)) # some empty space
s1Sizer.Add(self.s2lower, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s1Sizer, 1, wx.EXPAND)


# S1 and S2 HIGH label
femSizer.Add(s2label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s2Sizer = wx.BoxSizer(wx.HORIZONTAL)
s2Sizer.Add(self.s1upper, 1)
s2Sizer.Add((10,10)) # some empty space
s2Sizer.Add(self.s2upper, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s2Sizer, 1, wx.EXPAND)


# Volatility label
femSizer.Add(vlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
volSizer = wx.BoxSizer(wx.HORIZONTAL)
volSizer.Add(self.v1vol, 1)
volSizer.Add((10,10)) # some empty space
volSizer.Add(self.v2vol, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(volSizer, 1, wx.EXPAND)


# Risk free Rate and corelation
femSizer.Add(prlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
rcSizer = wx.BoxSizer(wx.HORIZONTAL)
rcSizer.Add(self.risk, 1)
rcSizer.Add((10,10)) # some empty space
rcSizer.Add(self.corr, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(rcSizer, 1, wx.EXPAND)


# Strike and Exercise Date
femSizer.Add(kTlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
ktSizer = wx.BoxSizer(wx.HORIZONTAL)
ktSizer.Add(self.strike, 1)
ktSizer.Add((10,10)) # some empty space
ktSizer.Add(self.finalT, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(ktSizer, 1, wx.EXPAND)


# deltaT and deltaX
femSizer.Add(dTXlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
dtxSizer = wx.BoxSizer(wx.HORIZONTAL)
dtxSizer.Add(self.deltaT, 1)
dtxSizer.Add((10,10)) # some empty space
dtxSizer.Add(self.deltaX, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(dtxSizer, 1, wx.EXPAND)


# now add the femSizer to the mainSizer
mainSizer.Add(femSizer, 0, wx.EXPAND|wx.ALL, 10)

# The buttons sizer will put them in a row with resizeable
# gaps between and on either side of the buttons
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add((10,10)) # some empty space
btnSizer.Add(runBtn)
btnSizer.Add((10,10)) # some empty space
mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.BOTTOM, 10)

panel.SetSizer(mainSizer)

# Fit the frame to the needs of the sizer. The frame will
# automatically resize the panel as needed. Also prevent the
# frame from getting smaller than this size.
mainSizer.Fit(self)
mainSizer.SetSizeHints(self)

def OnSubmit(self, evt):
s1low = self.s1lower.GetValue()
s2low = self.s2lower.GetValue()
s1high = self.s1upper.GetValue()
s2high = self.s2upper.GetValue()
s1vol = self.v1vol.GetValue()
s2vol = self.v2vol.GetValue()
irate = self.risk.GetValue()
pcorr = self.corr.GetValue()
kprice = self.strike.GetValue()
totalT = self.finalT.GetValue()
delT = self.deltaT.GetValue()
delX = self.deltaX.GetValue()
wx.MessageBox('You chose: \n %s \n %s \n %s \n %s \
\n %s \n %s \n %s' %
(s1low,s2low,s1high,s2high,s1vol,s2vol,irate))
# I want to do something like this below....
# return s1low,s2low,s1high,s2high,s1vol,s2vol,irate
This is the crux. Here you have to Destroy() the frame (self) for the
MainLoop to terminate properly, so you have to save the values before
you do that. So replace this whole method with something like

def OnSubmit(self, evt):
"The user has filled in the required values and want to run"
self.storage.s1low = self.s1lower.GetValue()
self.storage.s2low = self.s2lower.GetValue()
self.storage.s1high = self.s1upper.GetValue()
self.storage.s2high = self.s2upper.GetValue()
self.storage.s1vol = self.v1vol.GetValue()
self.storage.s2vol = self.v2vol.GetValue()
self.storage.irate = self.risk.GetValue()
self.storage.pcorr = self.corr.GetValue()
self.storage.kprice = self.strike.GetValue()
self.storage.totalT = self.finalT.GetValue()
self.storage.delT = self.deltaT.GetValue()
self.storage.delX = self.deltaX.GetValue()
self.Destroy()
class MyApp(wx.App):

def OnInit(self):
frame = FemInput()
self.SetTopWindow(frame)
frame.Show()
return True


# Needed if called as a module
if __name__ == '__main__':
app = MyApp(False)
app.MainLoop()


Good luck!

regards
Steve
 
T

Tyler

Hi Mike:

I actually just picked up the wxPython in Action book the other day
and my main class is a hack of his "realworld_print.py" program, with
some added bells and whistles. I will try to post on the wxPython
mailing list and let them have a go at it.

Cheers,

tyler
 
7

7stud

Hello All:

I am currently working on a project to create an FEM model for school.
I was thinking about using wxPython to gather the 12 input variables
from the user, then, after pressing the "Run" button, the GUI would
close, and the 12 input variables would then be available for the rest
of the program.

So far, what I have been able to do is mostly a reverse engineering
job to get the frame to look right and return the text variable to a
dialog box.

I have read about a "redirect" that could be used to send the values
to a file. But, then I would have to open the file and read in the
data from there. This seems crude and lacking elegance.

Any help on how to get the program to output the data back to the main
python program and close when I press submit? My apologies if this is
something of a simple question, but I have only started in on wxPython
about a week ago, and Python this term.

The codes I am using are below.

Any help (or suggested reading material) is greatly appreciated.

Cheers,

t.

MY MAIN PROGRAM

#!/usr/bin/env python
import femGUI
app = femGUI.MyApp(False)
dlg = femGUI.FemInput()
dlg.Destroy()
app.MainLoop()

# Then do something with inputs here....

THE FEMINPUT GUI CLASS

import wx

class FemInput(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Options Input Interface")
panel = wx.Panel(self)

# First create the controls

# Title
topLbl = wx.StaticText(panel, -1, "FEM 2D Basket Put Option
",size=(420,-1))
topLbl.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))

# S1 lower and upper bounds for grid
s1label = wx.StaticText(panel, -1, "S1 Low , S2 Low: ",
size=(220,-1))
self.s1lower = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2lower = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S2 lower and upper bounds for grid
s2label = wx.StaticText(panel, -1, "S1 High, S2 High: ",
size=(220,-1))
self.s1upper = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.s2upper = wx.TextCtrl(panel, -1, "", size=(100,-1));

# S1 and S2 volatility
vlabel = wx.StaticText(panel, -1, "S1 Volatility, S2
Volatility: ", size=(220,-1))
self.v1vol = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.v2vol = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Risk free rate and correlation
prlabel = wx.StaticText(panel, -1, "Interest Rate,
Correlation: ", size=(220,-1))
self.risk = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.corr = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Strike and Exercise Date
kTlabel = wx.StaticText(panel, -1, "Srike Price, Exercise
Date: ", size=(220,-1))
self.strike = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.finalT = wx.TextCtrl(panel, -1, "", size=(100,-1));

# deltaT and deltaX
dTXlabel = wx.StaticText(panel, -1, "delta T, delta X: ",
size=(220,-1))
self.deltaT = wx.TextCtrl(panel, -1, "", size=(100,-1));
self.deltaX = wx.TextCtrl(panel, -1, "", size=(100,-1));

# Execute program
runBtn = wx.Button(panel, -1, "Run")
self.Bind(wx.EVT_BUTTON, self.OnSubmit, runBtn)

# Now do the layout.

# mainSizer is the top-level one that manages everything
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(topLbl, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel), 0,
wx.EXPAND|wx.TOP|wx.BOTTOM, 5)

# femSizer is a grid that holds all of the address info
femSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
femSizer.AddGrowableCol(1)

# S1 and S2 LOWER label
femSizer.Add(s1label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s1Sizer = wx.BoxSizer(wx.HORIZONTAL)
s1Sizer.Add(self.s1lower, 1)
s1Sizer.Add((10,10)) # some empty space
s1Sizer.Add(self.s2lower, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s1Sizer, 1, wx.EXPAND)

# S1 and S2 HIGH label
femSizer.Add(s2label, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
s2Sizer = wx.BoxSizer(wx.HORIZONTAL)
s2Sizer.Add(self.s1upper, 1)
s2Sizer.Add((10,10)) # some empty space
s2Sizer.Add(self.s2upper, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(s2Sizer, 1, wx.EXPAND)

# Volatility label
femSizer.Add(vlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
volSizer = wx.BoxSizer(wx.HORIZONTAL)
volSizer.Add(self.v1vol, 1)
volSizer.Add((10,10)) # some empty space
volSizer.Add(self.v2vol, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(volSizer, 1, wx.EXPAND)

# Risk free Rate and corelation
femSizer.Add(prlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
rcSizer = wx.BoxSizer(wx.HORIZONTAL)
rcSizer.Add(self.risk, 1)
rcSizer.Add((10,10)) # some empty space
rcSizer.Add(self.corr, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(rcSizer, 1, wx.EXPAND)

# Strike and Exercise Date
femSizer.Add(kTlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
ktSizer = wx.BoxSizer(wx.HORIZONTAL)
ktSizer.Add(self.strike, 1)
ktSizer.Add((10,10)) # some empty space
ktSizer.Add(self.finalT, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(ktSizer, 1, wx.EXPAND)

# deltaT and deltaX
femSizer.Add(dTXlabel, 0,
wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
# the lower and upper S1 bounds are in a sub-sizer
dtxSizer = wx.BoxSizer(wx.HORIZONTAL)
dtxSizer.Add(self.deltaT, 1)
dtxSizer.Add((10,10)) # some empty space
dtxSizer.Add(self.deltaX, 1, wx.LEFT|wx.RIGHT, 5)
femSizer.Add(dtxSizer, 1, wx.EXPAND)

# now add the femSizer to the mainSizer
mainSizer.Add(femSizer, 0, wx.EXPAND|wx.ALL, 10)

# The buttons sizer will put them in a row with resizeable
# gaps between and on either side of the buttons
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add((10,10)) # some empty space
btnSizer.Add(runBtn)
btnSizer.Add((10,10)) # some empty space
mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.BOTTOM, 10)

panel.SetSizer(mainSizer)

# Fit the frame to the needs of the sizer. The frame will
# automatically resize the panel as needed. Also prevent the
# frame from getting smaller than this size.
mainSizer.Fit(self)
mainSizer.SetSizeHints(self)

def OnSubmit(self, evt):
s1low = self.s1lower.GetValue()
s2low = self.s2lower.GetValue()
s1high = self.s1upper.GetValue()
s2high = self.s2upper.GetValue()
s1vol = self.v1vol.GetValue()
s2vol = self.v2vol.GetValue()
irate = self.risk.GetValue()
pcorr = self.corr.GetValue()
kprice = self.strike.GetValue()
totalT = self.finalT.GetValue()
delT = self.deltaT.GetValue()
delX = self.deltaX.GetValue()
wx.MessageBox('You chose: \n %s \n %s \n %s \n %s \
\n %s \n %s \n %s' %
(s1low,s2low,s1high,s2high,s1vol,s2vol,irate))
# I want to do something like this below....
# return s1low,s2low,s1high,s2high,s1vol,s2vol,irate

class MyApp(wx.App):

def OnInit(self):
frame = FemInput()
self.SetTopWindow(frame)
frame.Show()
return True

# Needed if called as a module
if __name__ == '__main__':
app = MyApp(False)
app.MainLoop()


You can do this:

---
class MyFrame(wx.Frame):

...
...
...
def OnSubmit(self, event):
globals()["userInput"] = self.txtCtrlName.GetValue()
self.Close()

app = MyApp()
app.MainLoop()

print userInput
-----
 
S

Steve Holden

7stud said:
On Apr 19, 1:38 pm, Tyler <[email protected]> wrote:

[after quoting umpteen lines of code]
You can do this:

---
class MyFrame(wx.Frame):

..
..
..
def OnSubmit(self, event):
globals()["userInput"] = self.txtCtrlName.GetValue()
self.Close()

app = MyApp()
app.MainLoop()

print userInput


Please try to limit your quoting to what's relevant.

regards
Steve
 
K

kyosohma

7stud said:
On Apr 19, 1:38 pm, Tyler <[email protected]> wrote:

[after quoting umpteen lines of code]




You can do this:
..
..
..
def OnSubmit(self, event):
globals()["userInput"] = self.txtCtrlName.GetValue()
self.Close()
app = MyApp()
app.MainLoop()
print userInput
-----

Please try to limit your quoting to what's relevant.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
Recent Ramblings http://holdenweb.blogspot.com

Steve,

I think Tyler is opening a custom dialog from his main GUI
application. He should have used "ShowModal" if he was using one of
wxPython's standard dialog boxes, but since he was creating his own
custom one he didn't need to, which is why I told him to use the
self.Close(True) method to destroy the dialog. Then again, maybe I am
being "wrong-headed" about the whole thing.

I was trying to come up with the "instance variable" way of storing
the variables, but I could not think of how to implement it last
night. Here are some other threads on the topic that I thought were
interesting:

http://mail.python.org/pipermail/tutor/2005-May/038648.html
http://lists.wxwidgets.org/archive/wxPython-users/msg06482.html
http://www.daniweb.com/techtalkforums/thread60439.html

Mike
 
K

kyosohma

7stud said:
On Apr 19, 1:38 pm, Tyler <[email protected]> wrote:

[after quoting umpteen lines of code]




You can do this:
..
..
..
def OnSubmit(self, event):
globals()["userInput"] = self.txtCtrlName.GetValue()
self.Close()
app = MyApp()
app.MainLoop()
print userInput
-----

Please try to limit your quoting to what's relevant.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
Recent Ramblings http://holdenweb.blogspot.com

Steve,

I think Tyler is opening a custom dialog from his main GUI
application. He should have used "ShowModal" if he was using one of
wxPython's standard dialog boxes, but since he was creating his own
custom one he didn't need to, which is why I told him to use the
self.Close(True) method to destroy the dialog. Then again, maybe I am
being "wrong-headed" about the whole thing.

I was trying to come up with the "instance variable" way of storing
the variables, but I could not think of how to implement it last
night. Here are some other threads on the topic that I thought were
interesting:

http://mail.python.org/pipermail/tutor/2005-May/038648.html
http://lists.wxwidgets.org/archive/wxPython-users/msg06482.html
http://www.daniweb.com/techtalkforums/thread60439.html

Mike
 
S

Steve Holden

7stud said:
On Apr 19, 1:38 pm, Tyler <[email protected]> wrote:
[after quoting umpteen lines of code]




You can do this:
---
class MyFrame(wx.Frame):
..
..
..
def OnSubmit(self, event):
globals()["userInput"] = self.txtCtrlName.GetValue()
self.Close()
app = MyApp()
app.MainLoop()
print userInput
-----
Please try to limit your quoting to what's relevant.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
Recent Ramblings http://holdenweb.blogspot.com

Steve,

I think Tyler is opening a custom dialog from his main GUI
application. He should have used "ShowModal" if he was using one of
wxPython's standard dialog boxes, but since he was creating his own
custom one he didn't need to, which is why I told him to use the
self.Close(True) method to destroy the dialog. Then again, maybe I am
being "wrong-headed" about the whole thing.

I was trying to come up with the "instance variable" way of storing
the variables, but I could not think of how to implement it last
night. Here are some other threads on the topic that I thought were
interesting:

http://mail.python.org/pipermail/tutor/2005-May/038648.html
http://lists.wxwidgets.org/archive/wxPython-users/msg06482.html
http://www.daniweb.com/techtalkforums/thread60439.html
Well, if the whole application is GUI based then yes, the dialog should
inherit from wx.Dialog not wx.Frame, it should be opened using ShowModal
either at the click of a button or when the application starts, and
everything then becomes easy.

The "Run" button event handler should then call EndModal(wx.OK) - there
can also then be a cancel button that calls EndModal(wx>CANCEL), I
think, but it's been a while.

The advantage of this is that the dialog still exists after ShowModal()
returns (which is what the call to EndModal() causes to happen). So
usually you can do something like this (untested pseudo-code):

dlg = MyDialog(args_if_needed)
dlg.ShowModal()
something = dlg.Control.GetValue()
somethingElse = dlg.OtherControl.GetValue()
... repeat at will ...
dlg.Destroy()

This is the most often-used pattern for returning data from a dialog,
but it wasn't easy to see how to adapt that to Tyler's original code. I
made the mistake of assuming that Tyler knew a bit more about wxPython
that was actually the case, so I am sorry if the advice was off-target.

regards
Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top