aless80 aless80 - 4 months ago 17
Python Question

Starting wxPython and extending another class

I am switching from tkinter to wxPython and I am confused on inheritance when using template wxPython scripts similar to the wxexample class below. Given my three scripts below (mainClass.py, wxexample.py, callbacks.py), how do I:

1) properly start the wxPython window from the mainClass;

2) have the Example class extend the callbacks class below.

mainClass.py:

from time import sleep
import callbacks as clb
import wxexample

class mainClass(clb.callbacks): #, wxexample.Example):
def main(self):
#Here start the wxPython UI in wxexample!
...
#while 1: Edited
# sleep(0.5)

if __name__ == "__main__":
instance = mainClass()
instance.main()


wxexample.py:

import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()

def InitUI(self):
pnl = wx.Panel(self)
btn=wx.Button(pnl, label='Button', pos=(20, 30))
#Here I would like to call callbacks.mycallback as self.mycallback:
btn.Bind(wx.EVT_BUTTON, self.mycallback)
self.Show(True)


callbacks.py:

class callbacks():
def mycallback(self, e): #EDITED
print("callbacks.mycallback")


SOLVED: I went back to fundamentals and found this solution. I was confused because in my real implementation mainClass was extending wxexample.Example for other reasons, which throws an error (Cannot create a consistent method resolution order (MRO) for bases Example, Callbacks)

import callbacks as clb
import wxexample

class mainClass(clb.Callbacks): #, wxexample.Example):
def main(self):
wxexample.main()

if __name__ == "__main__":
instance = mainClass()
instance.main()


wxexample.py:

import wx
import callbacks as clb
class Example(wx.Frame, clb.Callbacks):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()

def InitUI(self):
pnl = wx.Panel(self)
btn=wx.Button(pnl, label='Button', pos=(20, 30))
#Here I would like to call callbacks.mycallback as self.mycallback:
btn.Bind(wx.EVT_BUTTON, self.mycallback)
self.Show(True)

def main():
ex = wx.App()
Example(None)
ex.MainLoop()

if __name__ == '__main__':
main()

Answer

All wxPython applications require the following, at a minimum:

  1. An instance of wx.App or a subclass derived from wx.App
  2. An instance of a top-level UI element, such as a wx.Frame, wx.Dialog or a derived class, which has been shown
  3. An event loop, almost always implemented by calling the application object's MainLoop method.

In light of that list, I worry about the while loop you show in your main method, as not using the main event loop, or blocking control from returning to it, will lead to more problems than you want to deal with when just learning the toolkit. You could replace that while loop with something like the following and that would put you on the right track:

app = wx.App()
frame = wxexample.Example(None, title="Example Frame")
app.MainLoop()

You'll also need to give mycallback an extra parameter as event handlers are always passed an event object, even if they do not need it.

If you haven't already, I recommend reading the tutorial at this site: http://zetcode.com/wxpython/

Comments