Binding class to menu item

This is certainly simple, but I have no examples in my prior code[1] and
cannot find an example on the Web, perhaps because I'm not using the proper
search string.

   In class MainFrame(wx.Frame) is the menu. For a menu item I want to bind a
class, ChangePasswordDialog(wx.Dialog) to that menu item:

   self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

wxPython tells me that ChangePasswordDialog() is not globally defined, but
it's not in the MainFrame class so the 'self' prefix is inappropriate. A
pointer to the proper syntax will be quite helpful.

TIA,

Rich
[1] In prior code the methods were in the same MainFrame class as the menu.

is it in the same file? if not, if you didn’t say:
from someFile import myClass

and instead are just saying:

import someFile

then your call to the class in the someFile needs to be:

someFile.myClass()

···

On Wednesday, July 16, 2014 2:44:42 PM UTC-7, fuzzydoc wrote:

This is certainly simple, but I have no examples in my prior code[1] and

cannot find an example on the Web, perhaps because I’m not using the proper

search string.

In class MainFrame(wx.Frame) is the menu. For a menu item I want to bind a

class, ChangePasswordDialog(wx.Dialog) to that menu item:

     self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

wxPython tells me that ChangePasswordDialog() is not globally defined, but

it’s not in the MainFrame class so the ‘self’ prefix is inappropriate. A

pointer to the proper syntax will be quite helpful.

TIA,

Rich

[1] In prior code the methods were in the same MainFrame class as the menu.

Nathan,

   Yes. All in the same module.

Rich

···

On Wed, 16 Jul 2014, Nathan McCorkle wrote:

is it in the same file?

Rich,
This is really a python question rather than a wxPython one,
whenever you refer to a function or any other item it can be:

···

On 16/07/14 22:44, Rich Shepard wrote:

    This is certainly simple, but I have no examples in my prior

code[1] and

  cannot find an example on the Web, perhaps because I'm not using

the proper

  search string.




    In class MainFrame(wx.Frame) is the menu. For a menu item I want

to bind a

  class, ChangePasswordDialog(wx.Dialog) to that menu item:




      self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)




  wxPython tells me that ChangePasswordDialog() is not globally

defined, but

  it's not in the MainFrame class so the 'self' prefix is

inappropriate. A

  pointer to the proper syntax will be quite helpful.




  TIA,




  Rich


  [1] In prior code the methods were in the same MainFrame class as

the menu.

  1. A global item in the same name space: just use
    ItemName
  2.     An item imported from elsewhere with from somewhere import
    

ItemName is added as a global in the current scope so use the
same so you can use from maths import (sin,pi);x=sin(pi/3).

  1. A member of the same class: use self.ItemName
  2.     A member of another class defined in the same scope or
    

imported from somewhere by the class name: use NameOfClassInstance .ItemName
i.e. if your class Parrot has a method IsDead you need to from
birds import Parrot;AmazonBlue=Parrot(…);if
AmazonBlue.IsDead():

  1.     A class method does not need an instance so you might be able
    

to use if from birds import Parrot;Parrot.IsDead():

  1.     Items that are global in a given import so can be used as
    

import birds:if birds.LaysEggs():
Basically if you have ChangePasswordDialog ** in the current
file** for your binding, (that name sounds like a window
rather than a function so I will assume that it is), you need a ** function** that takes an event as the input to bind. The usual is to
make that function be a member of the same class so you would use:
self.Bind(wx.EVT_MENU, self.On ChangePasswordDialog,
menuPasswd)

* Note no brackets as you are referring to the method not the

result of the method.*
and in your class have:
def OnChangePasswordDialog(self, evt):
# Create a ChangePasswordDialog, show it, process the result

  Hope that helps - for better examples look at the demos in the

Docs & Demos package - they are brilliant examples of how to
do things.

Gadget/Steve

Hi Gadget/Steve and Rich. Building on G/S's answer, I'd do it just a bit
differently, and to add in everything to possibly clarify it a bit more for
Rich:

import ChangePasswordDialog

self.Bind(wx.EVT_MENU, *self.On*PasswordDialogMenuItem, menuPasswd)

def *On*PasswordDialogMenuItem(self, evt):
    self.ShowChangePasswordDialog()

def ShowChangePasswordDialog():
   change_dlg = ChangePasswordDialog(...arguments...)
   result = change_dlg.ShowModal()
     # etc... do something with result, eventually destroy the dlg...or you
could do the style Werner
     # suggested, which is using a context manager (the "with" style)

I just like to name the event handlers in terms of the event they are
handling (here, using that menu item), and I also prefer to have a separate
function, named as a verb, that does whatever stuff I want the event
handler to kick off, but just call that function from the event handler
function. This way, if I later want to get to the ChangePasswordDialog
from some other means, there is already a function that just does that,
plus I have a clearly named verb-phrased function name in the namespace
that I can find in the IDE's explorer, whereas if it were just the handler,
I wouldn't be sure what it did.

Che

···

On Thu, Jul 17, 2014 at 1:09 AM, Steve Barnes <gadgetsteve@live.co.uk> wrote:

On 16/07/14 22:44, Rich Shepard wrote:

  This is certainly simple, but I have no examples in my prior code[1] and
cannot find an example on the Web, perhaps because I'm not using the
proper
search string.

  In class MainFrame(wx.Frame) is the menu. For a menu item I want to bind
a
class, ChangePasswordDialog(wx.Dialog) to that menu item:

    self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

wxPython tells me that ChangePasswordDialog() is not globally defined, but
it's not in the MainFrame class so the 'self' prefix is inappropriate. A
pointer to the proper syntax will be quite helpful.

TIA,

Rich
[1] In prior code the methods were in the same MainFrame class as the
menu.

Rich,

This is really a python question rather than a wxPython one, whenever you
refer to a function or any other item it can be:

   1. A *global* item in the same name space: just use ItemName
   2. An item imported from elsewhere with from somewhere import ItemName
   is added as a global in the current scope so use the same so you can use
   from maths import (sin,pi);x=sin(pi/3).
    3. A member of the same class: use self.ItemName
   4. A member of another class defined in the same scope or imported
   from somewhere by the class name: use NameOfClass*Instance*.ItemName
   i.e. if your class Parrot has a method IsDead you need to from birds import
   Parrot;AmazonBlue=Parrot(....);if AmazonBlue.IsDead():
   5. A class method does not need an instance so you might be able to
   use if from birds import Parrot;Parrot.IsDead():
   6. Items that are global in a given import so can be used as import
   birds:if birds.LaysEggs():

Basically if you have ChangePasswordDialog *in the current file* for your
binding, (that name sounds like a window rather than a function so I will
assume that it is), you need a *function *that takes an event as the
input to bind. The usual is to make that function be a member of the same
class so you would use:
self.Bind(wx.EVT_MENU, *self.On*ChangePasswordDialog, menuPasswd) # *Note
no brackets as you are referring to the method not the result of the
method.*
and in your class have:
def *On*ChangePasswordDialog(self, evt):
   #* Create a ChangePasswordDialog, show it, process the result*

This is really a python question rather than a wxPython one, whenever you
refer to a function or any other item it can be:

Steve,

   Yes, my basic python is as rusty as my wxPython.

Hope that helps - for better examples look at the demos in the Docs &
Demos package - they are brilliant examples of how to do things.

   It does.

Thanks,

Rich

···

On Thu, 17 Jul 2014, Steve Barnes wrote:

To further build on Gadget Steve and Che’s answers:

class ChangePasswordDialog(wx.Dialog):

Your dialog code goes here

Then in you main frame:

self.Bind(wx.EVT_MENU, self.onChangePasswordDlg, menuPasswd)

Later in your main frame:

def onChangePasswordDlg(self, event):

passwdDlg = ChangePasswordDialog()

if passwdDlg.ShowModal() == wx.ID_OK:

insert your code to continue the password changes.

What this does is create an instance of your ChangePasswordDialog class, then make it show as modal. By making it modal you prevent the user from doing anything else with your application until they finish resetting their password. The line if passwdDlg.ShowModal() == wx.ID_OK: also tells your program that the code within the statement should only be run IF the user clicks the “OK” / “Submit” button

···

On Wednesday, July 16, 2014 5:44:42 PM UTC-4, fuzzydoc wrote:

This is certainly simple, but I have no examples in my prior code[1] and

cannot find an example on the Web, perhaps because I’m not using the proper

search string.

In class MainFrame(wx.Frame) is the menu. For a menu item I want to bind a

class, ChangePasswordDialog(wx.Dialog) to that menu item:

     self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

wxPython tells me that ChangePasswordDialog() is not globally defined, but

it’s not in the MainFrame class so the ‘self’ prefix is inappropriate. A

pointer to the proper syntax will be quite helpful.

TIA,

Rich

[1] In prior code the methods were in the same MainFrame class as the menu.

Thanks again, Mike. That's the linkage I did not see.

Much appreciated,

Rich

···

On Thu, 17 Jul 2014, Mike Stover wrote:

To further build on Gadget Steve and Che's answers:

class ChangePasswordDialog(wx.Dialog):
   # Your dialog code goes here

Then in you main frame:

self.Bind(wx.EVT_MENU, self.onChangePasswordDlg, menuPasswd)

Later in your main frame:

def onChangePasswordDlg(self, event):
   passwdDlg = ChangePasswordDialog()
   if passwdDlg.ShowModal() == wx.ID_OK:
       # insert your code to continue the password changes.

But does it /need/ to be? It doesn’t seem like it, as this works:

import wx

class tc(object):

def __init__(self, event=None):

    print "initing tc"

    print repr(event)

class testFrame(wx.Frame):

def __init__(self):

    wx.Frame.__init__(self, parent=None, title="animate test", size=(200, 200))

    panel = wx.Panel(self, -1)

    sizer1 = wx.BoxSizer(wx.VERTICAL)

    sizer2 = wx.BoxSizer(wx.HORIZONTAL)

    btn = wx.Button(panel, -1, "Simple Widget")

    btn.Bind(wx.EVT_BUTTON, tc)

    sizer1.AddF(btn, wx.SizerFlags(0).Center())

    sizer2.AddF(sizer1,wx.SizerFlags(1).Center())

    panel.SetSizer(sizer2)

    panel.Layout()

if name == “main”:

app = wx.App(False)

frame = testFrame()

frame.Show()

app.MainLoop()
···

On Wednesday, July 16, 2014 10:09:40 PM UTC-7, Gadget Steve wrote:

Basically if you have ChangePasswordDialog ** in the current
file** for your binding, (that name sounds like a window
rather than a function so I will assume that it is), you need a ** function**that takes an event as the input to bind. The usual is to
make that function be a member of the same class

Rich Shepard wrote:

   This is certainly simple, but I have no examples in my prior code[1] and
cannot find an example on the Web, perhaps because I'm not using the proper
search string.

   In class MainFrame(wx.Frame) is the menu. For a menu item I want to bind a
class, ChangePasswordDialog(wx.Dialog) to that menu item:

   self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

I want to make sure you understand the key issue here. You can't bind a
class to an event. You can only bind a function. The function you
supply can create a new instance of the dialog and display it.

Also, just to be technical, you're not actually passing a class there.
You are creating a new object and passing that object.

···

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

You beat me to it. I realized that I hadn’t completely explained my example due to writing it while being distracted by other people asking me questions in person. Thank you for providing the details I forgot.

···

On Thursday, July 17, 2014 1:21:47 PM UTC-4, Tim Roberts wrote:

Rich Shepard wrote:

This is certainly simple, but I have no examples in my prior code[1] and

cannot find an example on the Web, perhaps because I’m not using the proper

search string.

In class MainFrame(wx.Frame) is the menu. For a menu item I want to bind a

class, ChangePasswordDialog(wx.Dialog) to that menu item:

     self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

I want to make sure you understand the key issue here. You can’t bind a

class to an event. You can only bind a function. The function you

supply can create a new instance of the dialog and display it.

Also, just to be technical, you’re not actually passing a class there.
You are creating a new object and passing that object.


Tim Roberts, ti...@probo.com

Providenza & Boekelheide, Inc.

There is a subtle difference between your example and his. You
had:
btn.Bind(wx.EVT_BUTTON, tc)
He had:
self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)
In your case you are passing a class. A class is “callable”, like a
function. Calling a class is how we create an instance. So, when
the event mechanism goes to trigger the event, it ends up creating a
temporary object, calling the constructor, and then discarding it.
In the original example, he has those extra parens. What he was
passing was not a class, but an instance of the class. An instance
is not “callable” (unless you supply a magic method).
In any case, what he was doing is not what he wanted to do.

···

Nathan McCorkle wrote:

    On Wednesday, July 16, 2014 10:09:40 PM UTC-7, Gadget Steve

wrote:

Basicall y if you have
ChangePasswordDialog in the current file for your binding, (that name sounds like a
window rather than a function so I will assume that it
is), you need a **
function** that takes an event
as the input to bind. The usual is to make that function be a member of
the same class

      But does it /need/ to be? It doesn't seem like it, as this

works:

-- Tim Roberts, Providenza & Boekelheide, Inc.

timr@probo.com

I’d think it would be passing the init function of that class…

···

On Thursday, July 17, 2014 10:28:31 AM UTC-7, Tim Roberts wrote:

There is a subtle difference between your example and his.   You

had:

        btn.Bind(wx.EVT_BUTTON, tc)

He had:

        self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)



In your case you are passing a class.  A class is "callable", like a

function.


No the init function will be called before the bind and return a
temporary class instance, (which will then be bound to the event),
so will need to be, itself, callable with a single parameter for the
event - it is possible to construct such a class but I suspect
rarely worth it.
Gadget/Steve

···

On 17/07/14 19:41, Nathan McCorkle
wrote:

    On Thursday, July 17, 2014 10:28:31 AM UTC-7, Tim Roberts wrote:
        There is a subtle

difference between your example and his. You had:

                btn.Bind(wx.EVT_BUTTON, tc)

        He had:

                self.Bind(wx.EVT_MENU, ChangePasswordDialog(),

menuPasswd)

        In your case you are passing a class.  A class is

“callable”, like a function.

      I'd think it would be passing the init function of that

class…

uhh, in the demo I posted of doing just this… the print in the init doesn’t show up until the event occurs.

···

On Thursday, July 17, 2014 11:55:19 AM UTC-7, Gadget Steve wrote:

  On 17/07/14 19:41, Nathan McCorkle > wrote:
    On Thursday, July 17, 2014 10:28:31 AM UTC-7, Tim Roberts wrote:
        There is a subtle

difference between your example and his. You had:

                btn.Bind(wx.EVT_BUTTON, tc)

        He had:

                self.Bind(wx.EVT_MENU, ChangePasswordDialog(),

menuPasswd)

        In your case you are passing a class.  A class is

“callable”, like a function.

      I'd think it would be passing the init function of that

class…


No the init function will be called before the bind and return a
temporary class instance, (which will then be bound to the event),
so will need to be, itself, callable with a single parameter for the
event - it is possible to construct such a class but I suspect
rarely worth it.

Gadget/Steve

Nope. In order to call the init function, there would have to
be an instance of the class (“self”), and there is no such object
here yet.
No, it is actually passing the class, which is itself an object. A
function is ALSO an object. In Python terms, both of those objects
happen to be “callables”, which means they have a “call” method
implemented. In the case of a class, the “call” method
allocates a new object, then calls the new and init methods.

···

Nathan McCorkle wrote:

    On Thursday, July 17, 2014 10:28:31 AM UTC-7, Tim Roberts wrote:
        There is a subtle

difference between your example and his. You had:

                btn.Bind(wx.EVT_BUTTON, tc)

        He had:

                self.Bind(wx.EVT_MENU, ChangePasswordDialog(),

menuPasswd)

        In your case you are passing a class.  A class is

“callable”, like a function.

      I'd think it would be passing the init function of that

class…

-- Tim Roberts, Providenza & Boekelheide, Inc.

timr@probo.com

I’m not sure how to interpret that, since as I said, I don’t see the print in the init function until I actually click the button. I don’t think a new class is being instantiated at event binding time… or we’re all missing some key info about Python objects/functions/classes.

···

On Thursday, July 17, 2014 12:19:34 PM UTC-7, Tim Roberts wrote:

Nathan McCorkle wrote:

    On Thursday, July 17, 2014 10:28:31 AM UTC-7, Tim Roberts wrote:
        There is a subtle

difference between your example and his. You had:

                btn.Bind(wx.EVT_BUTTON, tc)

        He had:

                self.Bind(wx.EVT_MENU, ChangePasswordDialog(),

menuPasswd)

        In your case you are passing a class.  A class is

“callable”, like a function.

      I'd think it would be passing the init function of that

class…

Nope.  In order to call the __init__ function, there would have to

be an instance of the class (“self”), and there is no such object
here yet.

No, it is actually passing the class, which is itself an object.  A

function is ALSO an object. In Python terms, both of those objects
happen to be “callables”, which means they have a “call” method
implemented. In the case of a class, the “call” method
allocates a new object, then calls the new and init methods.

No, what I said matches what you observe. You are passing the
“class object” – the object that is the class. That object gets
stored in the event machinery. When the event actually fires, the
code grabs that object and calls it, by invoking its call
method. For a class, the call method creates a new object (or
calls new to do that same task), then calls init.
Since the newly created object isn’t being stored anywhere, it will
then immediately get destroyed.

···

Nathan McCorkle wrote:

    On Thursday, July 17, 2014 12:19:34 PM UTC-7, Tim Roberts wrote:
        No, it is actually passing the class, which is itself an

object. A function is ALSO an object. In Python terms,
both of those objects happen to be “callables”, which means
they have a “call” method implemented. In the case of a
class, the “call” method allocates a new object, then
calls the new and init methods.

      I'm not sure how to interpret that, since as I said, I

don’t see the print in the init function until I actually
click the button. I don’t think a new class is being
instantiated at event binding time… or we’re all missing
some key info about Python objects/functions/classes.

-- Tim Roberts, Providenza & Boekelheide, Inc.

timr@probo.com

Ahh, ok, that makes sense… it’s the CLASS object, not an instantiation of that CLASS. In my demo, I replaced the class name in the Bind with className.call and get the same behavior! Cool!

I was actually going down a rat/rabbit-hole earlier-this/last week with overloading call and getattr to try a threaded object appear like a non-threaded object… I found a saner route to get around my problem though, but still glad to be ‘connecting the dots’.

···

On Thursday, July 17, 2014 1:12:58 PM UTC-7, Tim Roberts wrote:

No, what I said matches what you observe.  You are passing the

“class object” – the object that is the class. That object gets
stored in the event machinery. When the event actually fires, the
code grabs that object and calls it, by invoking its call
method. For a class, the call method creates a new object (or
calls new to do that same task), then calls init.


No, what I said matches what you observe. You are passing the "class
object" -- the object that is the class.

are you sure -- in what he posted, he had parens after than class name --
which would get evaluated when the bind code was run, which would result in
the event being bound to an instance. And if that instance wasn't callable
would result in a event-time error:

self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

but I suspect he really had:

self.Bind(wx.EVT_MENU, ChangePasswordDialog(), menuPasswd)

which would indeed pass a class object to the event binder, and its
__init__ would get called at event time.

-CHB

···

On Thu, Jul 17, 2014 at 1:12 PM, Tim Roberts <timr@probo.com> wrote:

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (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