[wxPython] Re: wxpython-users digest, Vol 1 #783 - 15 msgs

Robin told you the right answer, but since you seem to be just starting out,
and since you seem to be a bit confused by the event procedures, I wanted to
suggest some other things as well.

Tim Roberts wrote:

You should be able to replace that entire procedure with:

    def OnFindButton1(self,event):
        self.logger.AppendText('Found %s\n' % self.editname.GetValue())

#===========================================================================
Your code worked OK, but I am still puzzled by what is returned when the
button is pushed.

NOTHING is returned. Event handlers don't return anything. They just run.
When the button is pushed, OnFindButton1 will automatically be called. It
will take some action and then exit back to the windowing system until the
next event happens.

I modified the above code to:
#=================================================
def OnFindButton1(self,event):
  self.logger.AppendText('Found %s\n' %self.editname.GetValue())
  a = self.editname.GetValue()
  print 'This is the value of a: ',a
  print 'a is of type ',type(a)
  return self.editname.GetValue()

stuff = OnFindButton1
print 'Returned stuff from OnFindButton1 ',stuff
print 'stuff is of type ',type(stuff)
print ''

#=================================================
#..............which returns the following information:

pythonw -u Address2.py
Returned stuff from OnFindButton1 <function OnFindButton1 at 01545D0C>
stuff is of type <type 'function'>

As Robin said, OnFindButton1 is a function. The statement "stuff =
OnFindButton1" just makes stuff another reference to that function. To CALL
the function, you have to use parentheses. For example (JUST an example;
this won't actually work):

   stuff = OnFindButton1()

The reason this won't actually work is because OnFindButton1 requires two
parameters: an object of type "Form1", and a wx event. Since the procedure
doesn't actually use the "event" parameter, we can supply anything we want.
So, you COULD do this from your mainline code as:

   stuff = form1.OnFindButton1(None)
or from inside the class as:
   stuff = self.OnFindButton1(None)
   
But this is not how event procedures are used. The USUAL way to make this
code fire is to press the "Push" button in the window. You don't usually
call them on your own.

If all you want to do is get the text in the control, faking a call to an
event procedure is not the right way. Instead, since you save a copy of the
control in the object, you can refer to the control directly:

  print form1.editname.GetValue()

or from inside Form1:

  print self.editname.GetValue()

This is the value of a: asdfasdfasdf #......this is what I typed in the
window........
a is of type <type 'string'>
Exit code: 0
#======================================================

Although "self.editname.GetValue()" returns a sting inside the method, I
get a function returned
(instead of the string) when I ask the OnFindButton1 to "return
self.editname.GetValue()".

How can I get the string returned?

I'm not sure what you're asking here. Where do you want the string to be
returned to? Usually, in a main window like this, you read and use the
contents of the controls only within the methods of the frame's class. You
can use "self.editname.GetValue()" at any time, in any method of Form1, to
get the current contents of the control. You can save it in a file or in a
global, or whatever. You don't have to "capture" it at button-press time.

···

On Fri, 03 May 2002 15:33:39 -0400, Charles Bowman <bowman@acsu.buffalo.edu> wrote:

--
- Tim Roberts, timr@probo.com
  Providenza & Boekelheide, Inc.

Tim Roberts wrote:

[snip...]

If all you want to do is get the text in the control, faking a call to an
event procedure is not the right way. Instead, since you save a copy of the
control in the object, you can refer to the control directly:

  print form1.editname.GetValue()

or from inside Form1:

  print self.editname.GetValue()

I'm not sure what you're asking here. Where do you want the string to be
returned to? Usually, in a main window like this, you read and use the
contents of the controls only within the methods of the frame's class. You
can use "self.editname.GetValue()" at any time, in any method of Form1, to
get the current contents of the control. You can save it in a file or in a
global, or whatever. You don't have to "capture" it at button-press time.

--------------------------------------------------------------------------

I wish to save the text that is typed by the user to a global, and for
some reason, I am still
having difficulty doing this. (Sorry for the 'capture' terminology). I
have several other classes that will need this global information.

As before, the following code works OK, as far as it goes:

···

#=======================================================
Class Form1:
        [snipped code....full code is at the end of this email]
  .
  .
  .
  def EvtText(self, event):
    self.logger.AppendText('EvtText: %s\n' % event.GetString())
  
  def OnFindButton1(self,event):
    self.logger.AppendText('Found %s\n' %self.editname.GetValue())
    Name = self.editname.GetValue()
    print 'This is the value of Name: ',Name
    print 'Name is of type ',type(Name)
    return Name
#=======================================================
But I wish to have Name (or self.editname.GetValue()) used in other
parts of the program. Your suggestion of:
print self.editname.GetValue() added to class Form1 (outside of method
OnButton1) returns the following error:

pythonw -u Address2.py
Traceback (most recent call last):
  File "Address2.py", line 6, in ?
    class Form1(wxPanel):
  File "Address2.py", line 31, in Form1
    print self.editname.GetValue()
NameError: name 'self' is not defined

So, it appears that editname.GetValue() is local inside the procedure
(as is usual for Python).

I also tried a call to OnFindButton1:

stuff = OnFindButton1(None)
print stuff

This code returns the following error:

pythonw -u Address2.py
Traceback (most recent call last):
  File "Address2.py", line 6, in ?
    class Form1(wxPanel):
  File "Address2.py", line 32, in Form1
    stuff = OnFindButton1(None)
TypeError: OnFindButton1() takes exactly 2 arguments (1 given)
  
Your other suggestion to access editname from outside the class:
print 'Calling editname from Outside the Class Form1:
',form1.editname.GetValue()

(where form1 is an instance of the class Form1),

returns the following:

pythonw -u Address2.py
Calling editname from Outside the Class Form1: (<-----no text is
printed here)
This is the value of Name: asdfasdfasdfasdf (<------this is generated
by OnFindButton1...)
Name is of type <type 'string'> (<------also generated by
OnFindButton1...)

While I can access the user's input from inside a procedure, I cannot
use that information outside the procedure, or outside the class....

Once again, thanks for your help!

Charles Bowman

#==============================================================
Full Code shown here......

from wxPython.wx import *
from wxPython.html import *
import string,types
BTN1 = wxNewId()

class Form1(wxPanel):
  def __init__(self, parent, id):
    y = 60
    wxPanel.__init__(self, parent, id)
  
    # A multiline TextCtrl - This is here to show how the events work in
this program, don't pay too much attention to it
    self.logger = wxTextCtrl(self,5, "",wxPoint(300,20),
wxSize(200,300),wxTE_MULTILINE | wxTE_READONLY)
  
    self.lblname = wxStaticText(self, -1, "Name :",wxPoint(20,y))
    self.editname = wxTextCtrl(self, 20, "", wxPoint(100, y),
wxSize(200,-1))
    self.btn1 = wxButton(self,BTN1,"Push",wxPoint(210,y+20))

    EVT_TEXT(self, 20, self.EvtText)
    EVT_BUTTON(self,BTN1,self.OnFindButton1)
    
  def EvtText(self, event):
    self.logger.AppendText('EvtText: %s\n' % event.GetString())
  
  def OnFindButton1(self,event):
    self.logger.AppendText('Found %s\n' %self.editname.GetValue())
    Name = self.editname.GetValue()
    print 'This is the value of Name: ',Name
    print 'Name is of type ',type(Name)
    return Name
  #print self.editname.GetValue()
  #stuff = OnFindButton1(None)
  #print stuff

app = wxPySimpleApp()
frame = wxFrame(None, -1, "")
nb = wxNotebook(frame,-1)
form1=Form1(nb,-1)
nb.AddPage(form1, "Absolute Positing")
frame.Show(1)
#print 'Calling editname from Outside the Class Form1:
',form1.editname.GetValue()
#print 'Type of editname called from outside the class
',type(form1.editname.GetValue())
app.MainLoop()

#==============================================================
Full Code shown here......

from wxPython.wx import * from wxPython.html import *
import string,types
BTN1 = wxNewId()

class Form1(wxPanel): def __init__(self, parent, id): y = 60
    wxPanel.__init__(self, parent, id)
  
    # A multiline TextCtrl - This is here to show how the events work in
this program, don't pay too much attention to it self.logger = wxTextCtrl(self,5, "",wxPoint(300,20),
wxSize(200,300),wxTE_MULTILINE | wxTE_READONLY)
  
    self.lblname = wxStaticText(self, -1, "Name :",wxPoint(20,y)) self.editname = wxTextCtrl(self, 20, "", wxPoint(100, y),
wxSize(200,-1)) self.btn1 = wxButton(self,BTN1,"Push",wxPoint(210,y+20))

    EVT_TEXT(self, 20, self.EvtText) EVT_BUTTON(self,BTN1,self.OnFindButton1)

Form1.OnFindButton1 is a method of class Form1, so it expects to be passed an object of that class as its first argument (conventionally called self). x.OnFindButton1 is what Python calls a bound method, meaning that it already includes x as the Form1 to be passed as the first argument. As a result, x.OnFindButton1(event) is equivalent to Form1.OnFindButton1(x, event) (assuming x is an object of class Form1).

EVT_BUTTON expects a function f as its third argument. It will tell wxWindows to call f(event) when the button is pressed. By passing self.OnFindButton1, you tell call self.OnFindButton1(event), or equivalently Form1.OnFindButton1(x, event).

  def EvtText(self, event): self.logger.AppendText('EvtText: %s\n' % event.GetString())
  
  def OnFindButton1(self,event):
    self.logger.AppendText('Found %s\n' %self.editname.GetValue())
    Name = self.editname.GetValue()
    print 'This is the value of Name: ',Name
    print 'Name is of type ',type(Name)
    return Name

Yes, Name is local to the call to OnFindButton1 by default. If you wanted to store the value in a global variable worldName, you could write

def OnFindButton1(self, event):
   global worldName
   ...
   worldName = self.editname.GetValue()

Alternatively, you could store the value in an attribute of Form1 object, by writing

def OnFindButton1(self, event):
   ...
   self.Name = self.editname.GetValue()

Then, another method of Form1 could access that value as self.Name. Also, another part of the program which was not a method of Form1, but had a reference to form1 could access the name which was stored at the time of the most recent button press, by refering to form1.Name. Or, more cleanly, you could define another method

def getName(self):
   return self.Name

(I'm assuming you want the value which editname had the last time the button was pressed, even if editname has changed since. If you want the current value, you can just self.editname.GetValue() from within another method of Form1, or form1.editname.GetValue() from outside, as Tim said)

> But I wish to have Name (or self.editname.GetValue()) used in other
> parts of the program. Your suggestion of:
> print self.editname.GetValue() added to class Form1 (outside of method
> OnButton1) returns the following error:
>
> pythonw -u Address2.py
> Traceback (most recent call last):
> File "Address2.py", line 6, in ?
> class Form1(wxPanel):
> File "Address2.py", line 31, in Form1
> print self.editname.GetValue()
> NameError: name 'self' is not defined

I think when he said "from inside Form1" he meant from within a method of Form1 (either OnFindButton1, or another method). Otherwise the self variable won't necessarily be defined (or won't be equal to form1), which is why you are getting this error message.

>
> I also tried a call to OnFindButton1:
>
> stuff = OnFindButton1(None)
> print stuff
>
> This code returns the following error:
>
> pythonw -u Address2.py
> Traceback (most recent call last):
> File "Address2.py", line 6, in ?
> class Form1(wxPanel):
> File "Address2.py", line 32, in Form1
> stuff = OnFindButton1(None)
> TypeError: OnFindButton1() takes exactly 2 arguments (1 given)

As described about, OnFindButton1 is a method which expects two arguments, self and event. If you want to call it manually, you need to use form1.OnFindButton1(event) or Form1.OnFindButton1(form1, event).

>
> Your other suggestion to access editname from outside the class:
> print 'Calling editname from Outside the Class Form1:
> ',form1.editname.GetValue()
>
> (where form1 is an instance of the class Form1),
>
> returns the following:
>
> pythonw -u Address2.py
> Calling editname from Outside the Class Form1: (<-----no text is
> printed here)
> This is the value of Name: asdfasdfasdfasdf (<------this is generated
> by OnFindButton1...)
> Name is of type <type 'string'> (<------also generated by
> OnFindButton1...)

It looks like that worked fine. Of course, if you want to use the value, instead of just printing it, you'd have to say

some_name = form1.editname.GetValue()

David, Tim and Robin,

Still no luck making a global out of user input using wxTextCtrl. I'd
like to say I've written many Python programs in my two+ years
experience with Python (v.1.5 and 2.1) and have had zero (read: not
insurmountable) trouble with classes, methods, making Python queries for
Excel databases, making Python front ends for LaTeX templates and HTML
templates, and making Python front ends for plotting programs. Perhaps
my windows installation (NT, SP3) is not up to snuff for wxPython -
hybrid for python 2.1. Yet, the demos that came with wxPython appear to
work OK on NT SP3, and I got identical error messages on my Win98 box at
home (I have yet to try David's code suggestions on the Win98 box). I'd
go to a higher SP on my NT box, but there is one program I need that
will not run under SP4 (and you cannot return from SP4 to SP3, you have
reformat the disk, reinstall NT, etc, etc, etc,..).

Anyway, back to my life as a non-gui pythonic inputter........

Thanks for you help!

Regards,

Charles Bowman