Reputation: 27
EDITED ~ Now with code.
I’m new to coding, and struggling getting variables input into ‘frameA’ output into ‘frameB’. My question is, how should the layout of the code be written so that a variable entered into FrameA is usable, (and refreshed on user input - either on a button click or deselecting textctrl etc-) in frameB?
I’m using wxpython, and using Wx builder as a guide, but writing the actual UI code used myself to help understand what’s going on underneath. I’ve tried class -> def -> frame UI and the frames are organised as I want them, show and hide as I want and the variables I want are printable on entry/button clicks etc within that frame, but are not accessible from outside of that frame, even though I am returning the variables needed.
In this example I want to take what is written in frameA's textctrl, and save it as a variable accessible (and updated) to other classes, in this case FrameB.
import wx
var = "This Should change to whatever is typed in FrameA"
class FrameA ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = (0,0), size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
self.INPUT = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.INPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
self.SetSizer( bSizer1 )
self.INPUT.Bind( wx.EVT_TEXT, self.InputUpdate)
def InputUpdate(self, Evt):
var = self.INPUT.GetValue()
#print (var)
return var
class FrameB ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = (100,100), size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
self.OUTPUT = wx.StaticText( self, wx.ID_ANY, var, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.OUTPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
self.SetSizer( bSizer2 )
if __name__ == '__main__':
app = wx.App()
frmA = FrameA(None)
frmB = FrameB(None)
frmA.Centre()
frmB.Centre()
frmA.Show()
frmB.Show()
app.MainLoop()
As I’m still new I am at the point where I can understand each single line of code, but the larger organisation is still getting messy for me.
My understanding is that the code in its state above the edited 'var' can be accessed from within frameA only, and 'return var' might(?) update the 'global' var, but is not being refreshed into frameB. What am I missing? I've been trying to avoid using global variables as I've heard they're a bad habit to get into this early on...
Thanks, Sundown
Upvotes: 1
Views: 77
Reputation: 1436
If you want the value of var
to be accessible to all classes then you need to add the line global var
to the method InputUpdate()
in Class FrameA
before assigning the new value to var
.
However, this will make var
accessible to all classes in this module, only. If you split the code into two files, then you will have two modules and var
will be accessible only in the module that defines it, unless you also import the module defining var in the other module.
Code with some relevant comments:
import wx
var = "This Should change to whatever is typed in FrameA"
class FrameA ( wx.Frame ):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=(0,0), size=(500,300), style=wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.INPUT = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
bSizer1.Add(self.INPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
self.SetSizer(bSizer1)
self.INPUT.Bind(wx.EVT_TEXT, self.InputUpdate)
def InputUpdate(self, Evt):
#### You need to add the following line before assigning the new value to
#### var in order to modify the global var variable and not the local
#### var variable
global var
var = self.INPUT.GetValue()
#print (var)
#### The try/except block is placed to avoid having an error if the text
#### in frameA changes but frameB does not exist anymore. The code inside
#### the try statement changes the text in frameB in real time.
try:
frmB.OUTPUT.SetLabel(var)
except Exception:
pass
class FrameB ( wx.Frame ):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=(100,100), size=(500,300), style=wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)
bSizer2 = wx.BoxSizer(wx.VERTICAL)
self.OUTPUT = wx.StaticText(self, wx.ID_ANY, var, wx.DefaultPosition, wx.DefaultSize, 0)
bSizer2.Add(self.OUTPUT, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
#### Button to check the value of the global var variable and make sure
#### that the code in InputUpdate actually changes the value of the global
#### variable var
self.button = wx.Button(self, wx.ID_ANY, label='Var Value')
bSizer2.Add(self.button, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
self.SetSizer(bSizer2)
self.button.Bind(wx.EVT_BUTTON, self.varValue)
def varValue(self, event):
#### Print the value of the global variable var
print(var)
if __name__ == '__main__':
app = wx.App()
frmA = FrameA(None)
frmB = FrameB(None)
frmA.Centre()
frmB.Centre()
frmA.Show()
frmB.Show()
app.MainLoop()
Upvotes: 1