How to separate Gui and logic (Phoenix)

Keywords : Gui, Frame, Events handler, Widget.


Introduction :

I was sometimes ago playing around how to interact with classes and their methods.

I thought it will be better to share something.

Here is simple example to show how to work with methods from another class.

This can be helpful in separating GUI from logic (if you don't like xml/xrc).

Classes and interactions : this can be good in separating GUI from Logic Also can be used to separate different classes doing different jobs.

Programmed by Stephen Mtangoo Email : babaeliya@hotmail.com (United Republic of Tanzania).

Licenced under same LICENCE as wxpython.

Anybody can make it better, but don't change the main meaning / theme :

Just improvements are allowed.


Demonstrating :

Tested py3.x, wx4.x and Win10.

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)


First example

img_sample_one.png

ICON file : wxwin.ico

   1 # sample_one.py
   2 
   3 import wx
   4 
   5 # class MyFrame
   6 # class MyEvents
   7 # class MyApp
   8 
   9 #---------------------------------------------------------------------------
  10 
  11 class MyFrame(wx.Frame):
  12     def __init__(self, parent, id, title):
  13         wx.Frame.__init__(self, parent, id, title)
  14 
  15         self.SetIcon(wx.Icon("wxwin.ico"))
  16 
  17         #------------
  18 
  19         self.functions = MyEvents(self)
  20         self.panel = wx.Panel(self, -1)
  21 
  22         #------------
  23 
  24         # Add two buttons and text control.
  25         self.text = wx.TextCtrl(self.panel, -1)
  26         self.text.SetLabel("Hello world !")
  27         self.text.SetForegroundColour("white")
  28         self.text.SetBackgroundColour(wx.BLACK)
  29 
  30         self.button1 = wx.Button(self.panel, -1, "Red Colour")
  31         self.button2 = wx.Button(self.panel, -1, "Green Colour")
  32 
  33         #------------
  34 
  35         # Bind events to widgets.
  36         self.Bind(wx.EVT_BUTTON, self.functions.OnRed, id = self.button1.GetId())
  37         self.Bind(wx.EVT_BUTTON, self.functions.OnGreen, id = self.button2.GetId())
  38 
  39         #------------
  40 
  41         # Add them to sizer [define it first to prevent python
  42         # automatic detector to find you red handed].
  43         main = wx.BoxSizer(wx.VERTICAL)
  44         main.Add(self.text, 1, wx.EXPAND|wx.ALL, 1)
  45 
  46         #------------
  47 
  48         # Add buttons in separate sizer.
  49         sub_main = wx.BoxSizer(wx.HORIZONTAL)
  50         sub_main.Add(self.button1, 0, wx.EXPAND| wx.ALL, 5)
  51         sub_main.Add(self.button2, 0, wx.EXPAND| wx.ALL, 5)
  52         main.Add(sub_main, 0, wx.EXPAND| wx.ALL, 5)
  53 
  54         #------------
  55 
  56         # Set sizers to Frame through panel.
  57         self.panel.SetSizer(main)
  58         self.panel.Layout()
  59 
  60 #---------------------------------------------------------------------------
  61 
  62 class MyEvents():
  63     def __init__(self, parent):
  64 
  65         self.gui = parent
  66 
  67     #-----------------------------------------------------------------------
  68 
  69     def OnRed(self, evt):
  70         self.gui.text.SetBackgroundColour("Red")
  71 
  72         dlg = wx.MessageDialog(self.gui,
  73                                "Changed colour ! Click on the window to see !",
  74                                "Successful",
  75                                style = wx.ICON_INFORMATION| wx.OK)
  76         dlg.ShowModal()
  77         if dlg.ShowModal == wx.ID_OK:
  78             dlg.Destroy()
  79 
  80 
  81     def OnGreen(self, evt):
  82         self.gui.text.SetBackgroundColour(wx.GREEN)
  83 
  84         dlg = wx.MessageDialog(self.gui,
  85                                "Changed colour ! Click on the window to see !",
  86                                "Successful",
  87                                style = wx.ICON_INFORMATION| wx.OK)
  88         dlg.ShowModal()
  89         if dlg.ShowModal == wx.ID_OK:
  90             dlg.Destroy()
  91 
  92 #---------------------------------------------------------------------------
  93 
  94 class MyApp(wx.App):
  95     def OnInit(self):
  96 
  97         #------------
  98 
  99         frame = MyFrame(None, -1,
 100                         "Classes and interactions")
 101         self.SetTopWindow(frame)
 102         frame.Show(True)
 103 
 104         return True
 105 
 106 #---------------------------------------------------------------------------
 107 
 108 def main():
 109     app = MyApp(redirect=False)
 110     app.MainLoop()
 111 
 112 #---------------------------------------------------------------------------
 113 
 114 if __name__ == "__main__" :
 115     main()


Second example

img_sample_two.png

ICON file : wxwin.ico

   1 # sample_two.py
   2 
   3 import wx
   4 
   5 # class MyFrame
   6 # class MyEventsHandler
   7 # class MyApp
   8 
   9 #---------------------------------------------------------------------------
  10 
  11 class MyFrame(wx.Frame):
  12     def __init__(self, parent, id, title):
  13         wx.Frame.__init__(self, parent, -1, title=title)
  14 
  15         self.SetIcon(wx.Icon("wxwin.ico"))
  16 
  17         #------------
  18 
  19         self.frmPanel = wx.Panel(self)
  20         self.frmPanel.BackgroundColour = (200, 240, 250)    # light blue
  21 
  22         #------------
  23 
  24         # Add another panel and some buttons
  25         self.colourPnl = wx.Panel(self.frmPanel)
  26         self.colourPnl.SetBackgroundColour(wx.Colour('GREY'))
  27 
  28         #------------
  29 
  30         self.redBtn = wx.Button(self.frmPanel, label='Red')
  31         self.greenBtn = wx.Button(self.frmPanel, label='Green')
  32         self.exitBtn = wx.Button(self.frmPanel, label='Exit')
  33 
  34         #------------
  35 
  36         # Add them to sizer.
  37         colorPnlAndBtn_vSizer = wx.BoxSizer(wx.VERTICAL)
  38         colorPnlAndBtn_vSizer.Add(self.colourPnl, 1, wx.EXPAND|wx.ALL, 1)
  39 
  40         # Add buttons in their own sizer
  41         btn_hSizer = wx.BoxSizer(wx.HORIZONTAL)
  42         btn_hSizer.AddStretchSpacer()
  43         btn_hSizer.Add(self.redBtn, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
  44         btn_hSizer.Add(self.greenBtn, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
  45         btn_hSizer.Add(self.exitBtn, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
  46         btn_hSizer.AddStretchSpacer()
  47 
  48         colorPnlAndBtn_vSizer.Add(btn_hSizer, 0, wx.EXPAND| wx.ALL, 5)
  49 
  50         # SetSizer both sizers in the most senior control that has sizers in it.
  51         self.frmPanel.SetSizer(colorPnlAndBtn_vSizer)
  52         self.frmPanel.Layout()
  53 
  54         #------------
  55 
  56         # Must call before any event handler is referenced.
  57         self.eventsHandler = MyEventsHandler(self)
  58 
  59         #------------
  60 
  61         # Bind event handlers to all controls that have one.
  62         self.redBtn.Bind(wx.EVT_BUTTON, self.eventsHandler.OnRedBtn)
  63         self.greenBtn.Bind(wx.EVT_BUTTON, self.eventsHandler.OnGreenBtn)
  64         self.exitBtn.Bind(wx.EVT_BUTTON, self.eventsHandler.OnExitBtn)
  65 
  66         # Create more convenient ways to close this app.
  67         # Adding these makes a total of 5 separate ways to exit.
  68         self.frmPanel.Bind(wx.EVT_LEFT_DCLICK, self.eventsHandler.OnExitBtn)
  69         self.colourPnl.Bind(wx.EVT_LEFT_DCLICK, self.eventsHandler.OnExitBtn)
  70 
  71 #---------------------------------------------------------------------------
  72 
  73 class MyEventsHandler() :
  74     def __init__(self, parent):
  75 
  76         self.parent = parent
  77 
  78     #-----------------------------------------------------------------------
  79 
  80     def OnRedBtn(self, event):
  81         """
  82         ...
  83         """
  84 
  85         self.ShowColourAndDialog(wx.RED)
  86 
  87 
  88     def OnGreenBtn(self, event):
  89         """
  90         ...
  91         """
  92 
  93         self.ShowColourAndDialog(wx.GREEN)
  94 
  95 
  96     def ShowColourAndDialog(self, pnlColour):
  97         """
  98         ...
  99         """
 100 
 101         self.parent.colourPnl.SetBackgroundColour(pnlColour)
 102         self.parent.colourPnl.Refresh()
 103         dlg = wx.MessageDialog(self.parent, 'Changed colour !', 'Successful',
 104                                style = wx.ICON_INFORMATION| wx.OK)
 105         dlg.ShowModal()
 106         dlg.Destroy()
 107 
 108 
 109     def OnExitBtn(self, event):
 110         """
 111         ...
 112         """
 113 
 114         self.parent.Destroy()
 115 
 116 #---------------------------------------------------------------------------
 117 
 118 class MyApp(wx.App):
 119     def OnInit(self):
 120 
 121         #------------
 122 
 123         frame = MyFrame(None, -1,
 124                         "Separate the Gui from the logic")
 125         self.SetTopWindow(frame)
 126         frame.Show(True)
 127 
 128         return True
 129 
 130 #---------------------------------------------------------------------------
 131 
 132 def main():
 133     app = MyApp(redirect=False)
 134     app.MainLoop()
 135 
 136 #---------------------------------------------------------------------------
 137 
 138 if __name__ == "__main__" :
 139     main()


Download source

source.zip


Additional Information

Link :

- - - - -

https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/


Thanks to

Stephen Mtangoo (sample_one.py coding), Pool (sample_two.py coding), the wxPython community...


About this page

Date(d/m/y) Person (bot) Comments :

04/01/20 - Ecco (Updated page for wxPython Phoenix).


Comments

- blah, blah, blah....

How to separate Gui and logic (Phoenix) (last edited 2020-12-13 17:25:23 by Ecco)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.