944,110 Members | Top Members by Rank

Ad:
  • Python Discussion Thread
  • Marked Solved
  • Views: 5741
  • Python RSS
You are currently viewing page 1 of this multi-page discussion thread
Sep 24th, 2006
0

Calling button-click events from different classes

Expand Post »
Hi,

I am having a problem with function and class syntax.

I have one class (MakePanel1) that creates a button and label. The button-click event of the button is linked to a function (daclick1) that changes the text of the label. This works well.

I have another class (MakePanel2) that creates a second button. I want this second button to call the button-click function of the first button.

My incorrect call MakePanel1.daclick1() whilst in the MakePanel2 class produces the error ' TypeError: unbound method daclick1() must be called with MakePanel1 instance as first argument (got nothing instead) '.

Python Syntax (Toggle Plain Text)
  1. #!/usr/bin/python
  2.  
  3.  
  4. import wx
  5. import time
  6.  
  7.  
  8. class MakePanel1(wx.Panel):
  9. def __init__(self, Parent, *args, **kwargs):
  10. wx.Panel.__init__(self, Parent, *args, **kwargs)
  11.  
  12. self.dalabel = wx.StaticText(self, -1, " panel 1 label ")
  13. self.dabutton1 = wx.Button(self, label="button 1")
  14. self.dabutton1.Bind(wx.EVT_BUTTON, self.daclick1 )
  15. self.bs1 = wx.BoxSizer(wx.HORIZONTAL)
  16. self.bs1.Add(self.dabutton1,0)
  17. self.bs1.Add(self.dalabel,0)
  18. self.SetSizer(self.bs1)
  19.  
  20. def daclick1(self, event):
  21. self.dalabel.SetLabel(str(time.time()))
  22.  
  23.  
  24. class MakePanel2(wx.Panel):
  25. def __init__(self, Parent, *args, **kwargs):
  26. wx.Panel.__init__(self, Parent, *args, **kwargs)
  27.  
  28. self.dabutton2 = wx.Button(self, label="button 2")
  29. self.dabutton2.Bind(wx.EVT_BUTTON, self.daclick2 )
  30. self.bs2 = wx.BoxSizer(wx.HORIZONTAL)
  31. self.bs2.Add(self.dabutton2,0,wx.ALL,20)
  32. self.SetSizer(self.bs2)
  33.  
  34. def daclick2(self, event):
  35. MakePanel1.daclick1()
  36.  
  37. class DisFrame(wx.Frame):
  38. def __init__(self, *args, **kwargs):
  39. wx.Frame.__init__(self, *args, **kwargs)
  40.  
  41. self.Panel1 = MakePanel1(self)
  42. self.Panel2 = MakePanel2(self)
  43.  
  44. bs = wx.BoxSizer(wx.VERTICAL)
  45. bs.Add(self.Panel1,1,wx.EXPAND);
  46. bs.Add(self.Panel2,1,wx.EXPAND);
  47.  
  48. self.SetSizer(bs)
  49. self.Fit()
  50.  
  51.  
  52. if __name__ == '__main__':
  53. app = wx.App()
  54. daframe = DisFrame(None)
  55. daframe.Show()
  56. app.MainLoop()

How do I call the button-click function of button 1 whilst in the button-click function of button 2 ?

Any assistance appreciated. Thanks.
Last edited by dunderhead; Sep 24th, 2006 at 12:58 am.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dunderhead is offline Offline
20 posts
since Sep 2006
Sep 24th, 2006
0

Re: Calling button-click events from different classes

One solution to fix problem is to have MakePanel2 inherit MakePanel1, then you only need to create instance of MakePanel1 in MakePanel2. For some odd reason wx.BoxSizer() gets confused with the label location. Look the code over.
Python Syntax (Toggle Plain Text)
  1. #!/usr/bin/python
  2.  
  3.  
  4. import wx
  5. import time
  6.  
  7.  
  8. class MakePanel1(wx.Panel):
  9. def __init__(self, Parent, *args, **kwargs):
  10. wx.Panel.__init__(self, Parent, *args, **kwargs)
  11.  
  12. self.dalabel = wx.StaticText(self, -1, " panel 1 label ")
  13. self.dabutton1 = wx.Button(self, label="button 1")
  14. self.dabutton1.Bind(wx.EVT_BUTTON, self.daclick1 )
  15. self.bs1 = wx.BoxSizer(wx.HORIZONTAL)
  16. self.bs1.Add(self.dabutton1,0)
  17. self.bs1.Add(self.dalabel,0)
  18. self.SetSizer(self.bs1)
  19.  
  20. def daclick1(self, event):
  21. self.dalabel.SetLabel(str(time.time()))
  22.  
  23.  
  24. class MakePanel2(MakePanel1):
  25. """Note that MakePanel2 inherits MakePanel1"""
  26. def __init__(self, Parent, *args, **kwargs):
  27. wx.Panel.__init__(self, Parent, *args, **kwargs)
  28.  
  29. self.dabutton2 = wx.Button(self, label="button 2")
  30. self.dabutton2.Bind(wx.EVT_BUTTON, self.daclick2 )
  31. self.bs2 = wx.BoxSizer(wx.HORIZONTAL)
  32. self.bs2.Add(self.dabutton2,0,wx.ALL,20)
  33. self.SetSizer(self.bs2)
  34.  
  35. def daclick2(self, event):
  36. #MakePanel1.daclick1() # gives error, need to make instance first
  37. self.Panel1 = MakePanel1(self)
  38. self.Panel1.daclick1(self)
  39.  
  40. class DisFrame(wx.Frame):
  41. def __init__(self, *args, **kwargs):
  42. wx.Frame.__init__(self, *args, **kwargs)
  43.  
  44. self.Panel1 = MakePanel1(self)
  45. self.Panel2 = MakePanel2(self)
  46.  
  47. bs = wx.BoxSizer(wx.VERTICAL)
  48. bs.Add(self.Panel1,1,wx.EXPAND);
  49. bs.Add(self.Panel2,1,wx.EXPAND);
  50.  
  51. self.SetSizer(bs)
  52. self.Fit()
  53.  
  54.  
  55. if __name__ == '__main__':
  56. app = wx.App()
  57. daframe = DisFrame(None)
  58. daframe.Show()
  59. app.MainLoop()
Reputation Points: 404
Solved Threads: 180
Nearly a Posting Virtuoso
bumsfeld is offline Offline
1,422 posts
since Jul 2005
Sep 24th, 2006
0

Re: Calling button-click events from different classes

Thanks for the reply Bumsfeld.

Unfortunately your suggestion seems to create another panel on Panel2 (with a button and label), and this modification does not change the text of the label I wish to alter (on the first panel).

Even though I am a novice python user, I feel as though I must be able to call the button-click function of the first button through the button-click event of the second button using a proper syntax call.

I simply don't have a good understanding of how to access python objects and functions between classes.
Last edited by dunderhead; Sep 24th, 2006 at 1:25 pm.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dunderhead is offline Offline
20 posts
since Sep 2006
Sep 24th, 2006
0

Re: Calling button-click events from different classes

Aha, now I see it! All you need to do is reference daclick1() properly! Forget the inherited solution.
Python Syntax (Toggle Plain Text)
  1. #!/usr/bin/python
  2.  
  3.  
  4. import wx
  5. import time
  6.  
  7.  
  8. class MakePanel1(wx.Panel):
  9. def __init__(self, Parent, *args, **kwargs):
  10. wx.Panel.__init__(self, Parent, *args, **kwargs)
  11.  
  12. self.dalabel = wx.StaticText(self, -1, " panel 1 label ")
  13. self.dabutton1 = wx.Button(self, label="button 1")
  14. self.dabutton1.Bind(wx.EVT_BUTTON, self.daclick1 )
  15. self.bs1 = wx.BoxSizer(wx.HORIZONTAL)
  16. self.bs1.Add(self.dabutton1,0)
  17. self.bs1.Add(self.dalabel,0)
  18. self.SetSizer(self.bs1)
  19.  
  20. def daclick1(self, event):
  21. self.dalabel.SetLabel(str(time.time()))
  22.  
  23.  
  24. class MakePanel2(wx.Panel):
  25. """Note that MakePanel2 inherits MakePanel1"""
  26. def __init__(self, Parent, *args, **kwargs):
  27. wx.Panel.__init__(self, Parent, *args, **kwargs)
  28.  
  29. self.dabutton2 = wx.Button(self, label="button 2")
  30. self.dabutton2.Bind(wx.EVT_BUTTON, self.daclick2 )
  31. self.bs2 = wx.BoxSizer(wx.HORIZONTAL)
  32. self.bs2.Add(self.dabutton2,0,wx.ALL,20)
  33. self.SetSizer(self.bs2)
  34.  
  35. def daclick2(self, event):
  36. # reference daclick1() properly!!!!!!!
  37. daframe.Panel1.daclick1(self)
  38.  
  39. class DisFrame(wx.Frame):
  40. def __init__(self, *args, **kwargs):
  41. wx.Frame.__init__(self, *args, **kwargs)
  42.  
  43. self.Panel1 = MakePanel1(self)
  44. self.Panel2 = MakePanel2(self)
  45.  
  46. bs = wx.BoxSizer(wx.VERTICAL)
  47. bs.Add(self.Panel1,1,wx.EXPAND);
  48. bs.Add(self.Panel2,1,wx.EXPAND);
  49.  
  50. self.SetSizer(bs)
  51. self.Fit()
  52.  
  53.  
  54. if __name__ == '__main__':
  55. app = wx.App()
  56. daframe = DisFrame(None)
  57. daframe.Show()
  58. app.MainLoop()
Sorry, was sitting in my favorite internet bistro and got distracted by friends!
Last edited by bumsfeld; Sep 24th, 2006 at 2:16 pm.
Reputation Points: 404
Solved Threads: 180
Nearly a Posting Virtuoso
bumsfeld is offline Offline
1,422 posts
since Jul 2005
Sep 25th, 2006
0

Re: Calling button-click events from different classes

Many thanks Bumsfeld !

Your suggestion is perfect.

I was about to post the following solution before seeing your response:

Python Syntax (Toggle Plain Text)
  1. MakePanel1.daclick1(daframe.Panel1,None)
My proposal is definitely less elegant than your solution.

Thanks again.
Last edited by dunderhead; Sep 25th, 2006 at 10:16 am.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dunderhead is offline Offline
20 posts
since Sep 2006
Sep 27th, 2006
0

Re: Calling button-click events from different classes

Right. Python does not allow the use of unbound methods like

MyClass.method()

Instead, it always requires

my_inst = MyClass()
my_inst.method()

The reason I got confused by these things is that we can do things like

import random
random.randint(5)

which appears to be an unbound method. However, it's actually just a function residing in the random module.

Jeff
Reputation Points: 92
Solved Threads: 156
Practically a Master Poster
jrcagle is offline Offline
608 posts
since Jul 2006
Sep 28th, 2006
0

Re: Calling button-click events from different classes

Thanks Jeff.

Your explanation has helped to remove some confusion I've had about valid calling conventions.

I understand how your approach is required when accessing widgets created in a class - it seems logical that you need to create the widget first [ my_inst = MyClass() ] before attempting to access the widget in any way [ my_inst.method() ].

But what happens when a class consists only of functions without any creation of widgets ?
Does the call my_inst = MyClass() in such a case mean anything ?

Much appreciate your comments.
Last edited by dunderhead; Sep 28th, 2006 at 12:44 am.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dunderhead is offline Offline
20 posts
since Sep 2006
Sep 28th, 2006
0

Re: Calling button-click events from different classes

In the case of:
Python Syntax (Toggle Plain Text)
  1. import random
  2. random.randint(5)
random is a module, and you are using the namespace random. Note that random is not a class!

To find out if an object is a class use something like this:
Python Syntax (Toggle Plain Text)
  1. import inspect
  2. if inspect.isclass(object_name):
  3. print "object_name is a class"

Generally, Python recommends to start class names with a Capital letter. This disinguishes them from module namespaces.

Here is a case where making an instance of an empty class means something:
Python Syntax (Toggle Plain Text)
  1. class Employee:
  2. pass
  3.  
  4.  
  5. john = Employee() # Create an empty employee record/struct
  6. ted = Employee()
  7.  
  8. # fill the fields of the record/struct
  9. john.name = 'John Johnson'
  10. john.dept = 'computer lab'
  11. john.salary = 3000
  12.  
  13. ted.name = 'Ted Tetris'
  14. ted.dept = 'human resources'
  15. ted.salary = 5000
  16.  
  17. print "%s works in the %s and earns $%s/month" % (john.name, john.dept, john.salary)
In other words, you can create new class variables outside the class!
Last edited by Ene Uran; Sep 28th, 2006 at 2:43 pm.
Reputation Points: 625
Solved Threads: 211
Posting Virtuoso
Ene Uran is offline Offline
1,704 posts
since Aug 2005
Sep 28th, 2006
0

Re: Calling button-click events from different classes

Thanks Ene Uran. Your post is very informative.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dunderhead is offline Offline
20 posts
since Sep 2006
Sep 28th, 2006
0

Re: Calling button-click events from different classes

Click to Expand / Collapse  Quote originally posted by dunderhead ...

I understand how your approach is required when accessing widgets created in a class - it seems logical that you need to create the widget first [ my_inst = MyClass() ] before attempting to access the widget in any way [ my_inst.method() ].

But what happens when a class consists only of functions without any creation of widgets ?
Does the call my_inst = MyClass() in such a case mean anything ?
Indeed it does. Here's an example:

[php]
class Test(object):
def this(self, arg):
print "my arg: ", arg

a = Test()
[/php]
We can now "look" at a as follows:

>>> a
<__main__.Test object at 0x00B83F50>
>>> a.this
<bound method Test.this of <__main__.Test object at 0x00B83F50>>
>>>

So a lives in memory, and a.this does, also. In other words, the object consists of nothing more or less than the 'this' method.

BTW, you can come close to an "unbound" method call like this:

[php]
>>> Test().this(4) # not quite Test.this(4), but close!
my arg: 4
[/php]
which creates an unassigned instance of Test(), calls its this method with arg = 4, and following the result, garbage-collects the Test() object out of existence. It probably runs slowly for large objects and/or many invocations, but it does work.

Jeff
Reputation Points: 92
Solved Threads: 156
Practically a Master Poster
jrcagle is offline Offline
608 posts
since Jul 2006

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in Python Forum Timeline: Python Stat points...
Next Thread in Python Forum Timeline: Python ISU





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC