How to access component in Panel whoes parent is a Frame

let say I define a class which inherited form Frame. in the class
init I declare a Panel and a TextCtrl whose parent is the Panel :-

class MainWindow(wx.Frame):
def init(self,parent,id,title):
wx.Frame.init(self,parent,wx.ID_ANY, title, size = ( 200,200),

style=wx.DEFAULT_FRAME_STYLE|

wx.NO_FULL_REPAINT_ON_RESIZE)
panel=wx.Panel(self,-1)

    self.sizer=wx.BoxSizer(wx.VERTICAL)

    TextCtrl3 = wx.TextCtrl(panel,-1,"1")
    self.sizer.Add(TextCtrl1,1) .

.
.
def OnCalc(self,e):
self.panel.TextCtrl3.setValue(“Button Push”)
.
.
When I run this code I got this error:-

Traceback (most recent call last):
File “kitek.py”, line 60, in OnCalc
self.panel.TextCtrl3.setValue(“Button Push”)
AttributeError: ‘MainWindow’ object has no attribute ‘panel’

So how to access the TextCtrl3 from OnCalc() ?

···

And whoever does an atom’s weight of evil will see it.

make the panel=
a self.panel=

···

On Monday 26 December 2005 21:03, Mohammad Jeffry wrote:

let say I define a class which inherited form Frame. in the class __init__
I declare a Panel and a TextCtrl whose parent is the Panel :-

class MainWindow(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,parent,wx.ID_ANY, title, size = ( 200,200),

                                        style=wx.DEFAULT_FRAME_STYLE|
                                        wx.NO_FULL_REPAINT_ON_RESIZE)
        panel=wx.Panel(self,-1)

        self.sizer=wx.BoxSizer(wx.VERTICAL)

        TextCtrl3 = wx.TextCtrl(panel,-1,"1")
        self.sizer.Add(TextCtrl1,1) .
.
.
     def OnCalc(self,e):
        self.panel.TextCtrl3.setValue("Button Push")
.
.
When I run this code I got this error:-

Traceback (most recent call last):
  File "kitek.py", line 60, in OnCalc
    self.panel.TextCtrl3.setValue("Button Push")
AttributeError: 'MainWindow' object has no attribute 'panel'

So how to access the TextCtrl3 from OnCalc() ?

----
And whoever does an atom's weight of evil will see it.

--
  UC

--
Open Source Solutions 4U, LLC 1618 Kelly St
Phone: +1 707 568 3056 Santa Rosa, CA 95401
Cell: +1 650 302 2405 United States
Fax: +1 707 568 6416

well, looking over the code in more detail:
in your case. if you just need to access the one textctrl then assign the
object to self aka

self.TextCtrl3=wx.TextCtrl(...)

and in onCalc:

self.TextCtrl3.setValue("Button Push")

if you need more controls in the panel, assign the panel to self
(earlier mail) and give the controls decent Id's, i.e.
TextCtrl3 = wx.TextCtrl(panel,10000,"1")

and then find the TextXtrl by ID in the onCalc method

txt=self.panel.FindWindowById(10000)
txt.SetValue('whatever')

···

On Monday 26 December 2005 21:17, Uwe C. Schroeder wrote:

make the panel=
a self.panel=

On Monday 26 December 2005 21:03, Mohammad Jeffry wrote:
> let say I define a class which inherited form Frame. in the class
> __init__ I declare a Panel and a TextCtrl whose parent is the Panel :-
>
>
> class MainWindow(wx.Frame):
> def __init__(self,parent,id,title):
> wx.Frame.__init__(self,parent,wx.ID_ANY, title, size = (
> 200,200),
>
> style=wx.DEFAULT_FRAME_STYLE|
> wx.NO_FULL_REPAINT_ON_RESIZE)
> panel=wx.Panel(self,-1)
>
> self.sizer=wx.BoxSizer(wx.VERTICAL)
>
> TextCtrl3 = wx.TextCtrl(panel,-1,"1")
> self.sizer.Add(TextCtrl1,1) .
> .
> .
> def OnCalc(self,e):
> self.panel.TextCtrl3.setValue("Button Push")
> .
> .
> When I run this code I got this error:-
>
> Traceback (most recent call last):
> File "kitek.py", line 60, in OnCalc
> self.panel.TextCtrl3.setValue("Button Push")
> AttributeError: 'MainWindow' object has no attribute 'panel'
>
>
> So how to access the TextCtrl3 from OnCalc() ?
>
> ----
> And whoever does an atom's weight of evil will see it.

--
  UC

--
Open Source Solutions 4U, LLC 1618 Kelly St
Phone: +1 707 568 3056 Santa Rosa, CA 95401
Cell: +1 650 302 2405 United States
Fax: +1 707 568 6416

let say I define a class which inherited form Frame. in the class __init__
I declare a Panel and a TextCtrl whose parent is the Panel :-

To clarify Uwe, wxPython classes don't get anything more than any other
Python class.

class foo:
    def __init__(self):
        a = 1
        b = (a, 2)
    def bar(self):
        print self.b[0]

Would you expect calling foo().bar() to produce 1? Of course not, which
is why you should't expect self.panel.TextCtrl3.SetValue() to do
anything.

Further, even though you can use ctrl.GetChildren() to get the list of
children of a control in the order in which they were created, how would
you expect the internal implementation to pull out the names 'panel' and
'TextCtrl3' from the locals of __init__(), and not mistake them for
possibly temporary variables, and then also set them to be instance
variables of MainWindow (or the panel)?

Please people, read your exception messages, think about your exception
messages, and check the documentation.

- Josiah

···

Mohammad Jeffry <linuxlah@gmail.com> wrote:

class MainWindow(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,parent,wx.ID_ANY, title, size = ( 200,200),

                                        style=wx.DEFAULT_FRAME_STYLE|
                                        wx.NO_FULL_REPAINT_ON_RESIZE)
        panel=wx.Panel(self,-1)

        self.sizer=wx.BoxSizer(wx.VERTICAL)

        TextCtrl3 = wx.TextCtrl(panel,-1,"1")
        self.sizer.Add(TextCtrl1,1) .
.
.
     def OnCalc(self,e):
        self.panel.TextCtrl3.setValue("Button Push")
.
.
When I run this code I got this error:-

Traceback (most recent call last):
  File "kitek.py", line 60, in OnCalc
    self.panel.TextCtrl3.setValue("Button Push")
AttributeError: 'MainWindow' object has no attribute 'panel'

So how to access the TextCtrl3 from OnCalc() ?

----
And whoever does an atom's weight of evil will see it.

Hi,

First step:

Learn how to do OO programming in Python first! If you do some exercises with simple examples first, then you won't get wx issues mixed up with Python ones. There are a lot of good tutorials on the web and in books. The chapter on OO in "Learning Python" got me started.

        self.sizer=wx.BoxSizer(wx.VERTICAL)

        TextCtrl3 = wx.TextCtrl(panel,-1,"1")

As soon as I see this construction, I get nervous. Chances are you'd be better off making a custom Panel, and putting your TextCtrl on that. Then put the panel on the Frame separately. Like this:

#!/usr/bin/env python2.4
import wx

class MyPanel(wx.Panel):
     def __init__(self, parent, *args, **kwargs):
         wx.Panel.__init__(self, parent, *args, **kwargs)

         sizer=wx.BoxSizer(wx.VERTICAL)

         self.TextCtrl3 = wx.TextCtrl(self,-1,"1")
         sizer.Add(self.TextCtrl3, 1, wx.EXPAND)

         But = wx.Button(self, wx.ID_ANY, "Calc")
         But.Bind(wx.EVT_BUTTON, self.OnCalc)
         sizer.Add(But, 0, wx.ALL, 4)
         self.SetSizerAndFit(sizer)

     def OnCalc(self,e):
         self.TextCtrl3.SetValue("Button Push")

class TopFrame(wx.Frame):

     def __init__(self, *args, **kwargs):
         wx.Frame.__init__(self, *args, **kwargs)

         mypanel = MyPanel(self, wx.ID_ANY)

         self.Fit()

class MyApp(wx.App):

     def OnInit(self):
         self.topframe = TopFrame(None, wx.ID_ANY, "TEST")
         self.SetTopWindow(self.topframe)
         self.topframe.Show(True)
         return True

app = MyApp()
app.MainLoop()

This may look like extra work now, but it keeps your design cleaner and more structured, and keeps your namespaces from being cluttered and confusing.

Uwe C. Schroeder wrote:

in your case. if you just need to access the one textctrl then assign the object to self aka

self.TextCtrl3=wx.TextCtrl(...)

exactly.

if you need more controls in the panel, assign the panel to self
(earlier mail) and give the controls decent Id's, i.e.
TextCtrl3 = wx.TextCtrl(panel,10000,"1")

and then find the TextXtrl by ID in the onCalc method

txt=self.panel.FindWindowById(10000)
txt.SetValue('whatever')

This is a style issue, I suppose, but I would never do this!.

1) Use default IDs. (wx.ID_ANY, which equals -1, or use keyword arguments, and no ID at all)
2) Give your controls reasonable names
3) If you have a set of controls that all act similarly, then you might not want to give them all names, but you should store them in a pythonic manner, in a list or dictionary:

self.controls = {}
self.controls["A good name"] = wx.TextCtrl(panel, wx.ID_ANY, "1")

def OnCalc(self, e):
   txt=self.controls["A good Name"]
   txt.SetValue('whatever')

This doesn't look much different than just giving them names, but this way you can pass them around and act on them as a group. You can also automatically generate them more easily this way:

for i in range(NumberOfButtons):
     name = "Button#%i"%i
     self.controls[name] = wx.Button(self, label=name)

Magic numbers are bad. Meaningful names are good!

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov