├── .gitignore ├── Chapter07 ├── sample_data.csv ├── README.md ├── MyCSVViewerApp.py └── TemplateCSVViewerAppy.py ├── Chapter08 ├── README.md └── MyNotebookApp.py ├── wxPythonApp.png ├── Chapter09 ├── README.md └── CalculatorApp.py ├── Chapter01 ├── wxwindow_class_hierarchy.jpg ├── MyFirstApp.py ├── README.md └── MyFirstBetterLookingApp.py ├── Chapter10 ├── __pycache__ │ └── rw.cpython-36.pyc ├── README.md ├── rw.py └── RandomWalkApp.py ├── Chapter05 ├── README.md └── MyMenuBarApp.py ├── Chapter02 ├── README.md └── MyButtonApp.py ├── Chapter06 ├── README.md └── MyWebBrowser.py ├── Chapter04 ├── README.md └── MyButtonApp.py ├── Chapter03 ├── README.md └── MyMessageBoxApp.py └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/* 2 | -------------------------------------------------------------------------------- /Chapter07/sample_data.csv: -------------------------------------------------------------------------------- 1 | a,b,c,d 2 | 2,,, 3 | ,3,, 4 | ,,4, 5 | -------------------------------------------------------------------------------- /Chapter08/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 07 - Notebook 2 | 3 | Add notebook to panel 4 | -------------------------------------------------------------------------------- /wxPythonApp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Johnnyboycurtis/wxtutorials/HEAD/wxPythonApp.png -------------------------------------------------------------------------------- /Chapter09/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 09 - Calculator 2 | 3 | Here you will create a basic calculator. 4 | -------------------------------------------------------------------------------- /Chapter01/wxwindow_class_hierarchy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Johnnyboycurtis/wxtutorials/HEAD/Chapter01/wxwindow_class_hierarchy.jpg -------------------------------------------------------------------------------- /Chapter10/__pycache__/rw.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Johnnyboycurtis/wxtutorials/HEAD/Chapter10/__pycache__/rw.cpython-36.pyc -------------------------------------------------------------------------------- /Chapter10/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 10 - Random Walk Viz Tool 2 | 3 | Here is another example of a desktop application with wxPython. Here you will embed matplotlib graphics onto a panel for your desktop application. -------------------------------------------------------------------------------- /Chapter05/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 05 - Menu Bars 2 | 3 | In this tutorial, you'll learn how to add a menu bar and menus to the menu bar. 4 | 5 | ### References: 6 | 7 | 1. https://www.tutorialspoint.com/wxpython/wxpython_menus.htm 8 | -------------------------------------------------------------------------------- /Chapter02/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 02 2 | 3 | Here you will create another app with a button and an action. 4 | 5 | 6 | ## List of Events 7 | 8 | Some common events are wx.EVT_MENU, wx.EVT_BUTTON, wx.EVT_CLOSE. 9 | 10 | Reference: https://wiki.wxpython.org/ListOfEvents -------------------------------------------------------------------------------- /Chapter07/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 06 - Spreadsheet and Plot 2 | 3 | 4 | ### References: 5 | 6 | 1. https://wxpython.org/Phoenix/docs/html/grid_overview.html#grid-overview 7 | 8 | 2. [wxPython Application Development Cookbook](https://www.packtpub.com/application-development/wxpython-application-development-cookbook) -------------------------------------------------------------------------------- /Chapter01/MyFirstApp.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | app = wx.App(clearSigInt=True) # clearSigInt to allow terminating the program by CTRL+C 4 | frame = wx.Frame(parent=None, title="") ## main window object 5 | panel = wx.Panel(parent=frame) 6 | text = wx.StaticText(parent=panel, label="Hello, from wxPython!!", pos = (40,40)) 7 | frame.Show() 8 | app.MainLoop() -------------------------------------------------------------------------------- /Chapter06/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 05 - Web Browser 2 | 3 | Create a basic web browser; embed web content onto your desktop applications 4 | 5 | 6 | References: 7 | 8 | 1. https://wxpython.org/Phoenix/docs/html/wx.html2.1moduleindex.html 9 | 10 | 2. [wxPython Application Development Cookbook](https://www.packtpub.com/application-development/wxpython-application-development-cookbook) -------------------------------------------------------------------------------- /Chapter04/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 03 2 | 3 | Here you will create an app with more buttons, and learn to organize them with `wx`'s Sizers so your app doesn't look crummy. 4 | Additionally, you will use ArtProvider to source icons for your applications. 5 | 6 | 7 | ### References: 8 | 9 | 1. https://wiki.wxpython.org/BoxSizerTutorial 10 | 11 | 2. https://wxpython.org/Phoenix/docs/html/wx.ArtProvider.html -------------------------------------------------------------------------------- /Chapter01/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 01 2 | 3 | Here you will create your first silly app that does nothing special, but introduces you to `wx.App`, `wx.Frame` and `wx.Panel` which are three important components to creating apps in wxPython. 4 | 5 | Reference: https://www.tutorialspoint.com/wxpython/wxpython_major_classes.htm 6 | 7 | ## Understanding the hierarchy 8 | 9 | ![alt text](wxwindow_class_hierarchy.jpg "wxPython Hierarchy") -------------------------------------------------------------------------------- /Chapter03/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 03 - Message Box 2 | 3 | Here you will create an app with a message pop up box. 4 | 5 | ## Window Styles 6 | 7 | In this example, I used `wx.YES_NO` which puts Yes and No buttons in the message box. It is recommended to always use CANCEL with this style as otherwise the message box won’t have a close button under wxMSW and the user will be forced to answer it. On Windows, it is important to include `wx.CANCEL` to add a close button to the message window. Also included was `wx.CENTRE` style to center the message box on the parent window. 8 | 9 | Reference: https://wxpython.org/Phoenix/docs/html/wx.MessageDialog.html -------------------------------------------------------------------------------- /Chapter10/rw.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | 5 | 6 | class RandomWalk: 7 | def __init__(self, val = 15, steps = 100): 8 | self.steps = steps 9 | self.val = val 10 | y = np.zeros(shape=steps) 11 | y[0] = val 12 | for i in range(1, steps): 13 | y[i] = y[i-1] + np.random.randn() 14 | self.y = y 15 | 16 | def plot(self): 17 | plt.plot(self.y) 18 | plt.grid() 19 | plt.ylabel("y") 20 | plt.xlabel("steps") 21 | plt.ylim((min(self.y) - 5, max(self.y)+5)) 22 | plt.xlim((0, self.steps)) 23 | plt.title("Random Walk") 24 | plt.show() 25 | 26 | 27 | 28 | if __name__ == "__main__": 29 | demo = RandomWalk() 30 | demo.plot() 31 | -------------------------------------------------------------------------------- /Chapter01/MyFirstBetterLookingApp.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import webbrowser 3 | 4 | class MyApp(wx.App): 5 | def __init__(self): 6 | super().__init__(clearSigInt=True) 7 | 8 | # init frame 9 | self.InitFrame() 10 | 11 | def InitFrame(self): 12 | frame = MyFrame(parent=None, title="Basic Frame", pos=(100, 100)) 13 | frame.Show(True) 14 | 15 | 16 | class MyFrame(wx.Frame): 17 | # subclass of wx.Window; Frame is a top level window 18 | # A frame is a window whose size and position can (usually) be changed by the user. 19 | # Usually represents the first/main window a user will see 20 | def __init__(self, parent, title, pos=pos): 21 | super().__init__(parent=parent, title=title, pos=pos) 22 | 23 | def OnInit(self): 24 | panel = MyPanel(parent=self) 25 | 26 | 27 | class MyPanel(wx.Panel): 28 | # A panel is a window on which controls are placed. (e.g. buttons and text boxes) 29 | # wx.Panel class is usually put inside a wxFrame object. This class is also inherited from wxWindow class. 30 | def __init__(self,parent): 31 | super().__init__(parent=parent) 32 | 33 | # add a hello message to the panel 34 | welcomeText = wx.StaticText(self, id=wx.ID_ANY, label="Welcome to wxPython", pos=(20,20)) 35 | # ID_ANY means that we don’t care about the id 36 | 37 | 38 | if __name__ == "__main__": 39 | app = MyApp() 40 | app.MainLoop() 41 | -------------------------------------------------------------------------------- /Chapter02/MyButtonApp.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import webbrowser 3 | 4 | class MyApp(wx.App): 5 | def __init__(self): 6 | super().__init__(clearSigInt=True) 7 | 8 | # init frame 9 | self.InitFrame() 10 | 11 | def InitFrame(self): 12 | frame = MyFrame(parent=None, title="my button app", pos = (100, 100)) 13 | frame.Show() 14 | 15 | 16 | class MyFrame(wx.Frame): 17 | # subclass of wx.Window; Frame is a top level window 18 | # A frame is a window whose size and position can (usually) be changed by the user. 19 | # Usually represents the first/main window a user will see 20 | def __init__(self, parent, title, pos): 21 | super().__init__(parent=parent, title=title, pos=pos) 22 | self.OnInit() 23 | 24 | def OnInit(self): 25 | panel = MyPanel(parent=self) 26 | 27 | 28 | class MyPanel(wx.Panel): 29 | # A panel is a window on which controls are placed. (e.g. buttons and text boxes) 30 | # wx.Panel class is usually put inside a wxFrame object. This class is also inherited from wxWindow class. 31 | def __init__(self,parent): 32 | super().__init__(parent=parent) 33 | 34 | # add a hello message to the panel 35 | welcomeText = wx.StaticText(self, label="To learn wxPython, click the link below!", pos=(20,20)) 36 | 37 | # add a button to bring up the dialog box 38 | button = wx.Button(parent=self, label='Click Here!', pos = (20, 120)) 39 | button.Bind(wx.EVT_BUTTON, self.onSubmit) # bind action to button 40 | 41 | 42 | def onSubmit(self, event): 43 | # stuff for the submit button to do 44 | webbrowser.open('https://wxpython.org/Phoenix/docs/html/index.html') 45 | 46 | 47 | 48 | 49 | if __name__ == "__main__": 50 | app = MyApp() 51 | app.MainLoop() 52 | -------------------------------------------------------------------------------- /Chapter08/MyNotebookApp.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyApp(wx.App): 4 | def __init__(self): 5 | super().__init__() 6 | frame = MainFrame() 7 | frame.Show() 8 | 9 | class NBPage(wx.Panel): 10 | def __init__(self, parent, message): 11 | super().__init__(parent) 12 | text = wx.StaticText(parent=self, id=wx.ID_ANY, label=message, pos=(20,20)) 13 | 14 | class MainFrame(wx.Frame): 15 | def __init__(self): 16 | super().__init__(None, title="Simple Notebook Example", pos = (100, 100)) 17 | 18 | # Here we create a panel and a notebook on the panel 19 | self.p = wx.Panel(self) 20 | self.nb = wx.Notebook(self.p) # notebook will go on panel within a sizer 21 | 22 | # finally, put the notebook in a sizer for the panel to manage 23 | # the layout 24 | sizer = wx.BoxSizer() 25 | sizer.Add(window=self.nb, proportion=1, flag=wx.EXPAND) # The item will be expanded to fill the space assigned to the item. 26 | # set proporition = 1 to allow changes (i.e. new pages) 27 | self.p.SetSizer(sizer) 28 | 29 | self.createMenu() # initialize the menu bar 30 | 31 | def createMenu(self): 32 | menuBar = wx.MenuBar() 33 | 34 | fileMenu = wx.Menu() # first 35 | newItem = wx.MenuItem(parentMenu=fileMenu, id=wx.ID_NEW, 36 | text='New Page\tCtrl+N', helpString='Create New Page', 37 | kind=wx.ITEM_NORMAL) # subMenu is final option 38 | fileMenu.Append(newItem) 39 | self.Bind(event=wx.EVT_MENU, handler=self.onNewItem, source=newItem) 40 | 41 | # finally, append the File Menu 42 | menuBar.Append(fileMenu, '&File') 43 | 44 | # finally, add the Menu Bar 45 | self.SetMenuBar(menuBar) 46 | 47 | def onNewItem(self, event): 48 | count = self.nb.GetPageCount() + 1 # add 1 for extra page 49 | message = "This is page {}".format(count) 50 | page = NBPage(self.nb, message) 51 | self.nb.AddPage(page, "Page " + str(count)) 52 | 53 | 54 | 55 | if __name__ == "__main__": 56 | app = MyApp() 57 | app.MainLoop() -------------------------------------------------------------------------------- /Chapter06/MyWebBrowser.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx import html2 3 | 4 | class MyApp(wx.App): 5 | def OnInit(self): 6 | WebFrame(None, "Surfing the Web").Show() 7 | return True 8 | 9 | 10 | class WebFrame(wx.Frame): 11 | def __init__(self, parent, title): 12 | super().__init__(parent, title=title) 13 | 14 | self._browser = html2.WebView.New(self) 15 | self._browser.LoadURL("www.google.com") # home page 16 | self._bar = NavBar(self, self._browser) 17 | 18 | 19 | sizer = wx.BoxSizer(wx.VERTICAL) 20 | sizer.Add(self._bar, 0, wx.EXPAND) 21 | sizer.Add(self._browser, 1, wx.EXPAND) 22 | self.SetSizer(sizer) 23 | 24 | self.Bind(html2.EVT_WEBVIEW_TITLE_CHANGED, self.OnTitle) 25 | 26 | def OnTitle(self, event): 27 | self.Title = event.GetString() 28 | 29 | 30 | 31 | class NavBar(wx.Panel): 32 | def __init__(self, parent, browser): 33 | super().__init__(parent) 34 | 35 | self.browser = browser 36 | print("Current URL:", self.browser.GetCurrentURL()) 37 | self._url = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) 38 | self._url.SetHint("Enter URL here and press enter...") 39 | self._url.Bind(wx.EVT_TEXT_ENTER, self.onEnter) 40 | 41 | back = wx.Button(self, style=wx.BU_EXACTFIT) 42 | back.Bitmap = wx.ArtProvider.GetBitmap(wx.ART_GO_BACK, 43 | wx.ART_TOOLBAR) 44 | back.Bind(wx.EVT_BUTTON, self.goBack) 45 | 46 | fw = wx.Button(self, style=wx.BU_EXACTFIT) 47 | fw.Bitmap = wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD, 48 | wx.ART_TOOLBAR) 49 | fw.Bind(wx.EVT_BUTTON, self.goForward) 50 | 51 | sizer = wx.BoxSizer(wx.HORIZONTAL) 52 | sizer.Add(back, proportion=0, flag=wx.ALL, border=5) 53 | sizer.Add(fw, proportion=0, flag=wx.ALL, border=5) 54 | sizer.Add(window=self._url, proportion=1, flag=wx.EXPAND) 55 | self.SetSizer(sizer) 56 | 57 | 58 | def onEnter(self, event): 59 | self.browser.LoadURL(self._url.Value) 60 | 61 | def goBack(self, event): 62 | event.Enable(self.browser.CanGoBack()) 63 | self.browser.GoBack() 64 | 65 | def goForward(self, event): 66 | event.Enable(self.browser.CanGoForward()) 67 | self.browser.GoForward() 68 | 69 | 70 | 71 | if __name__ == "__main__": 72 | app = MyApp() 73 | app.MainLoop() 74 | 75 | -------------------------------------------------------------------------------- /Chapter03/MyMessageBoxApp.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyApp(wx.App): 5 | def __init__(self): 6 | super().__init__() 7 | 8 | def OnInit(self): 9 | frame = MyFrame(parent=None, title="This is a frame") 10 | frame.Show() 11 | return True 12 | 13 | 14 | class MyFrame(wx.Frame): 15 | # subclass of wx.Window; Frame is a top level window 16 | # A frame is a window whose size and position can (usually) be changed by the user. 17 | # Usually represents the first/main window a user will see 18 | def __init__(self, parent, title): 19 | super().__init__(parent=parent, title=title, pos = (100, 100)) 20 | 21 | self.OnInit() 22 | 23 | def OnInit(self): 24 | panel = MyPanel(self) 25 | 26 | 27 | class MyPanel(wx.Panel): 28 | # A panel is a window on which controls are placed. (e.g. buttons and text boxes) 29 | # wx.Panel class is usually put inside a wxFrame object. This class is also inherited from wxWindow class. 30 | def __init__(self,parent): 31 | super().__init__(parent=parent) 32 | self._dont_show = False # for message dialog box 33 | 34 | # add a hello message to the panel 35 | welcomeText = wx.StaticText(self, label="Hello World!", pos=(20,20)) 36 | 37 | # add a text box 38 | self._text = wx.TextCtrl(parent= self, value = 'ENTER SOME TEXT HERE', pos = (20,60), size=(300, 50)) 39 | 40 | # add a button to bring up the dialog box 41 | self._button = wx.Button(parent=self, label='Submit', pos = (20, 120)) 42 | self._button.Bind(wx.EVT_BUTTON, self.onSubmit) # bind action to button 43 | 44 | 45 | def ShowDialog(self): 46 | # pop up a message dialog window on submit! 47 | if self._dont_show: 48 | return None 49 | 50 | dlg = wx.RichMessageDialog(parent=None, 51 | message= "Are you ready to learn wxPython?", 52 | caption="wxPythonStuff", 53 | style=wx.YES_NO|wx.CANCEL|wx.CENTRE) 54 | dlg.ShowCheckBox("Don't show this again") 55 | dlg.ShowModal() # shows the dialog 56 | 57 | if dlg.IsCheckBoxChecked(): 58 | print("Is check box checked?", dlg.IsCheckBoxChecked()) 59 | self._dont_show=True 60 | 61 | 62 | def onSubmit(self, event): 63 | # stuff for the submit button to do 64 | print(self._text.GetValue()) 65 | self.ShowDialog() 66 | 67 | 68 | 69 | 70 | if __name__ == "__main__": 71 | app = MyApp() 72 | frame = MyFrame(parent=None, title="This is a frame") 73 | app.MainLoop() 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wxtutorials 2 | 3 | ![alt text](wxPythonApp.png "Basic App") 4 | 5 | 6 | 7 | ## What is this? 8 | 9 | This is a repository of wxPython tutorials. It is to accompany the lecture videos I've uploaded (pending) to YouTube. 10 | 11 | - Link to be added upon video uploads 12 | 13 | ## Requirements 14 | 15 | - wxPython version 4.0.2+ 16 | 17 | - Python 3.6+ 18 | 19 | - Some python experience (strongly recommended) 20 | 21 | - Git (recommended, you're on Github) 22 | 23 | - Bash-like terminal (recommended) 24 | 25 | 26 | ## Who is this for? 27 | 28 | People who 29 | 30 | - don't want to learn PyQT and don't want to pay for the liscensing. 31 | 32 | - need a simple GUI platform 33 | 34 | Better looking platforms exist, but wxPython can be quick and easy to develop applications in. 35 | 36 | 37 | ## Set up 38 | 39 | All code was written on a Ubuntu machine, but is compatible with *most* Windows machines. If you are developing natively on Windows, be sure to have a Unix like terminal available like Git-bash or Ubuntu terminal. 40 | 41 | ### Terminal stuff 42 | 43 | - [Git Bash](https://git-scm.com/downloads) 44 | 45 | - [Install the Linux Subsystem on Windows 10 | Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 46 | 47 | 48 | You will need Git to clone this project directory 49 | 50 | git clone https://github.com/Johnnyboycurtis/wxtutorials.git 51 | 52 | 53 | ### Python stuff 54 | 55 | All code was developed using Python 3.6+ and wxPython 4.0.2. If you are still using Python 2, please consider migrating to Python 3 as support is for version 2 is limited; see [count down](https://pythonclock.org). 56 | 57 | #### Flavor of Python 58 | 59 | There are many flavors of Python. I recommend using Anaconda's [Miniconda](https://conda.io/miniconda.html); not the full blown Anaconda download. 60 | 61 | #### Environments 62 | 63 | For your sanity's sake, I *highly* recommend using `virtualenv` or `conda`'s environments. I use miniconda; you can create a new environment with whatever version of Python you'd like with a simple command 64 | 65 | 66 | conda create -n myenv python=3.6 67 | 68 | and activate it on your system's (bash) terminal with 69 | 70 | source activate myenv 71 | 72 | 73 | Reference: [Managing environments — Conda documentation](https://conda.io/docs/user-guide/tasks/manage-environments.html) 74 | 75 | 76 | #### Installing packages 77 | 78 | To install `wxPython` and all other necessary packages, run 79 | 80 | conda install -c anaconda wxpython 81 | conda install matplotlib numpy ipython 82 | 83 | 84 | 85 | 86 | ## Still confused? 87 | 88 | Here are some helpful resources, but beware, they may be outdated 89 | 90 | - http://zetcode.com/wxpython/ 91 | 92 | - https://wiki.wxpython.org/How%20to%20Learn%20wxPython 93 | 94 | - https://www.tutorialspoint.com/wxpython/ 95 | 96 | 97 | ### New to Python? 98 | 99 | I recommend Corey Schafer's [Python Tutorials](https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTskrapNbzXhwoFUiLCjGgY7&index=1) 100 | 101 | 102 | ### How do I become an expert? 103 | 104 | Practice, my friend. [Complexity and the Ten-Thousand-Hour Rule](https://www.newyorker.com/news/sporting-scene/complexity-and-the-ten-thousand-hour-rule) -------------------------------------------------------------------------------- /Chapter07/MyCSVViewerApp.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.grid as gridlib 3 | import csv 4 | 5 | class MyApp(wx.App): 6 | def __init__(self): 7 | super().__init__(clearSigInt=True) 8 | 9 | # init frame 10 | self.InitFrame() 11 | 12 | def InitFrame(self): 13 | frame = MyFrame(parent=None, title="Basic Frame") 14 | frame.Show(True) 15 | 16 | 17 | class MyFrame(wx.Frame): 18 | def __init__(self, parent, title): 19 | super().__init__(parent=parent, title=title) 20 | self.OnInit() 21 | 22 | def OnInit(self): 23 | # first creat some dummy panel to hold some text 24 | titlePanel = MyPanel(parent=self) 25 | 26 | # create sizers to control layout 27 | mainSizer = wx.BoxSizer(wx.VERTICAL) 28 | titleSizer = wx.BoxSizer(wx.HORIZONTAL) 29 | gridSizer = wx.BoxSizer(wx.HORIZONTAL) 30 | 31 | titleSizer.Add(titlePanel, 0, wx.ALL, 5) 32 | mainSizer.Add(titleSizer, 0, wx.CENTER) 33 | mainSizer.Add(wx.StaticLine(self,), 0, wx.ALL|wx.EXPAND, 5) 34 | 35 | # data viewer 36 | grid = GridTable(self) 37 | grid.LoadFile() 38 | grid.SetColReadOnly(0) 39 | gridSizer.Add(grid, 1, wx.ALL|wx.EXPAND, 5) 40 | mainSizer.Add(gridSizer, 0, wx.ALL|wx.EXPAND, 5) 41 | 42 | self.SetSizer(mainSizer) 43 | mainSizer.Fit(self) 44 | 45 | 46 | class MyPanel(wx.Panel): 47 | def __init__(self,parent): 48 | super().__init__(parent=parent) 49 | welcomeText = wx.StaticText(self, label="Data Grid Display", pos=(20,20)) 50 | 51 | 52 | 53 | class GridTableSource(gridlib.GridTableBase): 54 | def __init__(self): 55 | super().__init__() 56 | self._data = None 57 | self._header = None 58 | self._readOnly = list() 59 | 60 | def LoadFile(self, fileName='./sample_data.csv'): 61 | fileName = './sample_data.csv' 62 | reader = csv.reader(open(fileName, 'r')) 63 | self._data = [row for row in reader] 64 | self._header = self._data.pop(0) 65 | self._readOnly = list() 66 | 67 | def Sort(self, col, ascending): 68 | #self._data.sort(key=lambda data: data[col], reverse=True) 69 | pass 70 | 71 | def SetColReadOnly(self, col): 72 | self._readOnly.append(col) 73 | 74 | def GetNumberRows(self): 75 | return len(self._data) if self._data else 0 76 | 77 | def GetNumberCols(self): 78 | return len(self._header) if self._header else 0 79 | 80 | def GetValue(self, row, col): 81 | if not self._data: 82 | return "" 83 | else: 84 | return self._data[row][col] 85 | 86 | def SetValue(self, row, col, value): 87 | if self._data: 88 | self._data[row][col] = value 89 | 90 | def GetColLabelValue(self, col): 91 | return self._header[col] if self._header else None 92 | 93 | 94 | 95 | class GridTable(gridlib.Grid): 96 | def __init__(self, parent): 97 | super().__init__(parent) 98 | 99 | self._data = GridTableSource() 100 | self.SetTable(self._data) 101 | 102 | # need to implement a sorting event; else sementation fault error 103 | self.Bind(gridlib.EVT_GRID_COL_SORT, self.OnSort) 104 | 105 | def OnSort(self, event): 106 | self._data.Sort(event.Col, 107 | self.IsSortOrderAscending()) 108 | 109 | def LoadFile(self, fileName='./sample_data.csv'): 110 | self._data.LoadFile(fileName) 111 | self.SetTable(self._data) 112 | self.AutoSizeColumns() 113 | 114 | 115 | def SetColReadOnly(self, col): 116 | self._data.SetColReadOnly(col) 117 | 118 | 119 | if __name__ == "__main__": 120 | app = MyApp() 121 | app.MainLoop() 122 | -------------------------------------------------------------------------------- /Chapter05/MyMenuBarApp.py: -------------------------------------------------------------------------------- 1 | import os 2 | import wx 3 | 4 | class MyApp(wx.App): 5 | def __init__(self): 6 | super().__init__() 7 | 8 | frame = MyFrame(parent=None, title="Menu Bar App") 9 | frame.Show() 10 | 11 | 12 | class FileMenu(wx.Menu): 13 | def __init__(self, parentFrame): 14 | super().__init__() 15 | self.OnInit() 16 | self.parentFrame = parentFrame 17 | 18 | def OnInit(self): 19 | newItem = wx.MenuItem(parentMenu=self, id=wx.ID_NEW, text="&New\tCtrl+N", kind=wx.ITEM_NORMAL) 20 | self.Append(newItem) 21 | 22 | openItem = wx.MenuItem(parentMenu=self, id=wx.ID_OPEN, text='&Open\tCtrl+O', kind=wx.ITEM_NORMAL) 23 | self.Append(openItem) 24 | self.Bind(wx.EVT_MENU, handler=self.onOpen, source=openItem) 25 | 26 | saveItem = wx.MenuItem(parentMenu=self, id=wx.ID_SAVE, text="&Save\tCtrl+S", helpString="Save your file", kind=wx.ITEM_NORMAL) 27 | self.Append(saveItem) 28 | self.Bind(wx.EVT_MENU, handler=self.onSave, source=saveItem) 29 | 30 | self.AppendSeparator() 31 | 32 | radioItem1 = wx.MenuItem(self, id=200, text = "Option 1", kind = wx.ITEM_RADIO) 33 | self.Append(radioItem1) 34 | radioItem2 = wx.MenuItem(self, id=300, text = "Option 2", kind = wx.ITEM_RADIO) 35 | self.Append(radioItem2) 36 | 37 | self.AppendSeparator() 38 | 39 | quitItem = wx.MenuItem(parentMenu=self, id=wx.ID_EXIT, text='&Quit\tCtrl+Q') 40 | self.Append(quitItem) 41 | self.Bind(wx.EVT_MENU, handler=self.onQuit, source=quitItem) 42 | 43 | def onOpen(self, event): 44 | wildcard = "TXT files (*.txt)|*.txt" 45 | dialog = wx.FileDialog(self.parentFrame, "Open Text Files", wildcard=wildcard, 46 | style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) 47 | 48 | if dialog.ShowModal() == wx.ID_CANCEL: 49 | return None 50 | 51 | path = dialog.GetPath() 52 | if os.path.exists(path): 53 | with open(path) as myfile: 54 | for line in myfile: 55 | self.parentFrame.text.WriteText(line) 56 | 57 | def onSave(self, event): 58 | dialog = wx.FileDialog(self.parentFrame, message="Save your data", 59 | defaultFile="Untitled.txt", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) 60 | 61 | if dialog.ShowModal() == wx.ID_CANCEL: 62 | return None 63 | 64 | path = dialog.GetPath() 65 | data = self.parentFrame.text.GetValue() 66 | print(data) 67 | data = data.split('\n') 68 | print(data) 69 | with open(path, "w+") as myfile: 70 | for line in data: 71 | myfile.write(line+"\n") 72 | 73 | 74 | def onQuit(self, event): 75 | self.parentFrame.Close() 76 | 77 | 78 | class EditMenu(wx.Menu): 79 | def __init__(self): 80 | super().__init__() 81 | self.OnInit() 82 | 83 | def OnInit(self): 84 | copyItem = wx.MenuItem(self, 100,text = "Copy",kind = wx.ITEM_NORMAL) 85 | self.Append(copyItem) 86 | cutItem = wx.MenuItem(self, 101,text = "Cut",kind = wx.ITEM_NORMAL) 87 | self.Append(cutItem) 88 | pasteItem = wx.MenuItem(self, 102,text = "Paste",kind = wx.ITEM_NORMAL) 89 | self.Append(pasteItem) 90 | 91 | 92 | class MyFrame(wx.Frame): 93 | def __init__(self, parent, title): 94 | super().__init__(parent, title = title, size = (500, 400)) 95 | self.InitUI() 96 | 97 | def InitUI(self): 98 | self.text = wx.TextCtrl(parent=self, id=wx.ID_ANY, style = wx.EXPAND|wx.TE_MULTILINE) 99 | menuBar = wx.MenuBar() 100 | 101 | fileMenu = FileMenu(parentFrame=self) 102 | menuBar.Append(fileMenu, '&File') 103 | 104 | editMenu = EditMenu() 105 | menuBar.Append(editMenu, '&Edit') 106 | 107 | self.SetMenuBar(menuBar) 108 | 109 | #self.Bind(wx.EVT_MENU, self.MenuHandler) 110 | self.Centre() 111 | self.Show(True) 112 | 113 | 114 | if __name__ == '__main__': 115 | app = MyApp() 116 | app.MainLoop() -------------------------------------------------------------------------------- /Chapter09/CalculatorApp.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | buttons = ["7", "8", "9", "/", 5 | "4", "5", "6", "*", 6 | "1", "2", "3", "-", 7 | "0", ".", "+", "="] 8 | 9 | 10 | 11 | class CalcFrame(wx.Frame): 12 | def __init__(self, parent, title, size, buttons): 13 | super().__init__(parent=parent, size=size, title=title) 14 | self.p = CalcPanel(parent=self, buttons=buttons) 15 | self.p.Layout() 16 | self.Show(True) 17 | 18 | 19 | 20 | class CalcPanel(wx.Panel): 21 | def __init__(self, parent, buttons): 22 | super().__init__(parent=parent) 23 | self._buttons = buttons 24 | 25 | self.makeButtons() 26 | 27 | def makeButtons(self): 28 | specialButtons = [wx.Button(parent=self, id=wx.ID_ANY, label="Clear")] # special calculator menu buttons 29 | mainButtons = [wx.Button(parent=self, id=wx.ID_ANY, label=b) for b in self._buttons] 30 | self.display = wx.TextCtrl(self, style= wx.TE_READONLY, value="", size=(240,50)) #wx.StaticText(self, wx.ID_ANY, 'OUTPUT HERE') 31 | self.needs_reset_display=False 32 | 33 | mainSizer = wx.BoxSizer(orient=wx.VERTICAL) 34 | displaySizer = wx.BoxSizer(orient=wx.HORIZONTAL) 35 | rowZero = wx.BoxSizer(orient=wx.HORIZONTAL) # special buttons like clear 36 | rowOne = wx.BoxSizer(orient=wx.HORIZONTAL) 37 | rowTwo = wx.BoxSizer(orient=wx.HORIZONTAL) 38 | rowThree = wx.BoxSizer(orient=wx.HORIZONTAL) 39 | rowFour = wx.BoxSizer(orient=wx.HORIZONTAL) 40 | 41 | displaySizer.Add(self.display) 42 | 43 | rowZero.Add(specialButtons[0], 0, wx.ALL, 5) 44 | 45 | rowOne.Add(mainButtons[0], 0, wx.ALL, 5) 46 | rowOne.Add(mainButtons[1], 0, wx.ALL, 5) 47 | rowOne.Add(mainButtons[2], 0, wx.ALL, 5) 48 | rowOne.Add(mainButtons[3], 0, wx.ALL, 5) 49 | 50 | rowTwo.Add(mainButtons[4], 0, wx.ALL, 5) 51 | rowTwo.Add(mainButtons[5], 0, wx.ALL, 5) 52 | rowTwo.Add(mainButtons[6], 0, wx.ALL, 5) 53 | rowTwo.Add(mainButtons[7], 0, wx.ALL, 5) 54 | 55 | rowThree.Add(mainButtons[8], 0, wx.ALL, 5) 56 | rowThree.Add(mainButtons[9], 0, wx.ALL, 5) 57 | rowThree.Add(mainButtons[10], 0, wx.ALL, 5) 58 | rowThree.Add(mainButtons[11], 0, wx.ALL, 5) 59 | 60 | rowFour.Add(mainButtons[12], 0, wx.ALL, 5) 61 | rowFour.Add(mainButtons[13], 0, wx.ALL, 5) 62 | rowFour.Add(mainButtons[14], 0, wx.ALL, 5) 63 | rowFour.Add(mainButtons[15], 0, wx.ALL, 5) 64 | 65 | 66 | 67 | ## then bind all buttons to events 68 | for i in range(15): 69 | print("BUTTON:", mainButtons[i].GetLabel()) 70 | self.Bind(wx.EVT_BUTTON, self.onSelect, mainButtons[i]) 71 | 72 | self.Bind(wx.EVT_BUTTON, self.onEqual, mainButtons[15]) 73 | self.Bind(wx.EVT_BUTTON, self.onClear, specialButtons[0]) 74 | 75 | mainSizer.Add(displaySizer, 1, wx.ALL | wx.ALIGN_CENTER, 5) 76 | #mainSizer.Add(wx.StaticLine(self,), 0, wx.ALL|wx.EXPAND, 5) # divider 77 | mainSizer.AddStretchSpacer() 78 | mainSizer.Add(rowZero, 0,wx.ALL | wx.ALIGN_CENTER, 5) 79 | mainSizer.Add(rowOne, 0, wx.ALL | wx.ALIGN_CENTER, 5) 80 | mainSizer.Add(rowTwo, 0, wx.ALL | wx.ALIGN_CENTER, 5) 81 | mainSizer.Add(rowThree, 0, wx.ALL | wx.ALIGN_CENTER, 5) 82 | mainSizer.Add(rowFour, 0, wx.ALL | wx.ALIGN_CENTER, 5) 83 | 84 | self.SetSizer(mainSizer) 85 | mainSizer.Fit(self.Parent) 86 | mainSizer.Layout() 87 | 88 | 89 | def onSelect(self,event): 90 | buttonSelected = event.GetEventObject() 91 | text = buttonSelected.GetLabel() 92 | if text in "+-/*": 93 | text = " " + text + " " # add some simple spacing 94 | print(text) 95 | self.display.AppendText(text) 96 | 97 | def onEqual(self, event): 98 | text = self.display.GetLineText(0) 99 | print(text) 100 | result = str(eval(text)) # evaluate the string the convert back to string 101 | print(result) 102 | self.display.SetValue(result) 103 | 104 | def onClear(self, event): 105 | self.display.Clear() 106 | 107 | 108 | 109 | if __name__ == "__main__": 110 | app = wx.App(False) 111 | frame = CalcFrame(None, title='Calculator', size=(400, 300), buttons=buttons) 112 | app.MainLoop() -------------------------------------------------------------------------------- /Chapter07/TemplateCSVViewerAppy.py: -------------------------------------------------------------------------------- 1 | # Chapter 5: Data Displays and Grids 2 | # Recipe 4: Getting started with the data grid 3 | # 4 | import csv 5 | from io import StringIO 6 | import wx 7 | import wx.grid as gridlib 8 | 9 | class CSVDataSource(gridlib.GridTableBase): 10 | def __init__(self): 11 | super().__init__() 12 | self._data = None 13 | self._header = None 14 | self._readOnly = list() 15 | 16 | self._roAttr = gridlib.GridCellAttr() 17 | self._roAttr.SetReadOnly() 18 | c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT) 19 | self._roAttr.TextColour = c 20 | 21 | def LoadFile(self, fileName='./sample_data.csv'): 22 | fileName = './sample_data.csv' 23 | reader = csv.reader(open(fileName, 'r')) 24 | self._data = [row for row in reader] 25 | self._header = self._data.pop(0) 26 | self._readOnly = list() 27 | 28 | def GetData(self): 29 | if not self._data: 30 | return "" 31 | 32 | buff = StringIO() 33 | writer = csv.writer(buff) 34 | writer.writerow(self._header) 35 | writer.writerows(self._data) 36 | print(buff.getvalue()) 37 | return buff.getvalue() 38 | 39 | def SetColReadOnly(self, col): 40 | self._readOnly.append(col) 41 | 42 | def GetAttr(self, row, col, kind): 43 | if col in self._readOnly: 44 | self._roAttr.IncRef() 45 | return self._roAttr 46 | return None 47 | 48 | def Sort(self, col, ascending): 49 | self._data.sort(None, lambda data: data[col], not ascending) 50 | 51 | def GetNumberRows(self): 52 | return len(self._data) if self._data else 0 53 | 54 | def GetNumberCols(self): 55 | return len(self._header) if self._header else 0 56 | 57 | def GetValue(self, row, col): 58 | if not self._data: 59 | return "" 60 | else: 61 | return self._data[row][col] 62 | 63 | def SetValue(self, row, col, value): 64 | if self._data: 65 | self._data[row][col] = value 66 | 67 | def GetColLabelValue(self, col): 68 | return self._header[col] if self._header else None 69 | 70 | class CSVEditorGrid(gridlib.Grid): 71 | def __init__(self, parent): 72 | super().__init__(parent) 73 | 74 | self._data = CSVDataSource() 75 | self.SetTable(self._data) 76 | 77 | self.Bind(gridlib.EVT_GRID_COL_SORT, self.OnSort) 78 | 79 | def OnSort(self, event): 80 | self._data.Sort(event.Col, 81 | self.IsSortOrderAscending()) 82 | 83 | def LoadFile(self, fileName): 84 | self._data.LoadFile(fileName) 85 | self.SetTable(self._data) 86 | self.AutoSizeColumns() 87 | 88 | def SaveFile(self, fileName): 89 | with open(fileName, 'w+') as fileObj: 90 | fileObj.write(self._data.GetData()) 91 | 92 | def SetColReadOnly(self, col): 93 | self._data.SetColReadOnly(col) 94 | 95 | #------- Sample Application ---------# 96 | 97 | class MyFrame(wx.Frame): 98 | def __init__(self, parent, title): 99 | super(MyFrame, self).__init__(parent, title=title) 100 | 101 | menub = wx.MenuBar() 102 | fmenu = wx.Menu() 103 | fmenu.Append(wx.ID_OPEN) 104 | fmenu.Append(wx.ID_SAVE) 105 | menub.Append(fmenu, "File") 106 | self.SetMenuBar(menub) 107 | self.CreateStatusBar() 108 | 109 | sizer = wx.BoxSizer() 110 | self._file = 'sample_data.csv' 111 | self._grid = CSVEditorGrid(self) 112 | self._grid.LoadFile(self._file) 113 | self._grid.SetColReadOnly(0) 114 | 115 | sizer.Add(self._grid, 1, wx.EXPAND) 116 | self.SetSizer(sizer) 117 | self.SetInitialSize() 118 | 119 | self.Bind(wx.EVT_MENU, self.OnSave, id=wx.ID_SAVE) 120 | self.Bind(wx.EVT_MENU, self.OnOpen, id=wx.ID_OPEN) 121 | 122 | def OnOpen(self, event): 123 | dlg = wx.FileDialog(self, "Open CSV File", wildcard="*.csv") 124 | result = dlg.ShowModal() 125 | if result == wx.ID_OK: 126 | self._grid.LoadFile(dlg.Path) 127 | dlg.Destroy() 128 | 129 | def OnSave(self, event): 130 | self._grid.SaveFile(self._file) 131 | self.SetStatusText("Saved file: %s" % self._file) 132 | 133 | class MyApp(wx.App): 134 | def OnInit(self): 135 | self.frame = MyFrame(None, title="Data Grid") 136 | self.frame.Show(); 137 | return True 138 | 139 | if __name__ == "__main__": 140 | app = MyApp(False) 141 | app.MainLoop() 142 | -------------------------------------------------------------------------------- /Chapter10/RandomWalkApp.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | matplotlib.use('WXAgg') 3 | 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | 7 | 8 | from matplotlib.backends.backend_wxagg import FigureCanvas # FigureCanvasWxAgg as FigureCanvas 9 | #from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg 10 | 11 | #from matplotlib.backends.backend_wx import _load_bitmap 12 | from matplotlib.figure import Figure 13 | 14 | import wx 15 | import rw 16 | 17 | class MyApp(wx.App): 18 | def __init__(self): 19 | super().__init__(clearSigInt=True) 20 | 21 | # run frame 22 | self.InitFrame() 23 | 24 | def InitFrame(self): 25 | frame = wx.Frame(parent=None, title="Random Walk", size=(600, 550)) 26 | frame._panel = MyPanel(frame) 27 | frame.Show(True) 28 | 29 | 30 | class MyFrame(wx.Frame): 31 | # subclass of wx.Window; Frame is a top level window 32 | # A frame is a window whose size and position can (usually) be changed by the user. 33 | # Usually represents the first/main window a user will see 34 | def __init__(self, parent, title, size): 35 | super().__init__(parent=parent, title=title, size=size) 36 | 37 | class MyPanel(wx.Panel): 38 | # A panel is a window on which controls are placed. (e.g. buttons and text boxes) 39 | # wx.Panel class is usually put inside a wxFrame object. This class is also inherited from wxWindow class. 40 | def __init__(self,parent): 41 | super().__init__(parent=parent) 42 | self._dont_show = False # for message dialog box 43 | 44 | self.Decorate() 45 | 46 | def Decorate(self): 47 | # add a hello message to the panel 48 | title = wx.StaticText(self, label="Random Walk Tool", pos=(20,20)) 49 | 50 | # add separator 51 | separator = wx.StaticLine(self, style=wx.LI_HORIZONTAL) 52 | 53 | muLabel = wx.StaticText(parent=self, label="mu: ") 54 | self.muInput = self.stepsInput = wx.SpinCtrl(parent=self, value="0", min=0, max=100) # replace txtctrl with spin button 55 | 56 | stepsLabel = wx.StaticText(parent=self, label="Number of Steps: ") 57 | self.stepsInput = self.stepsInput = wx.SpinCtrl(parent=self, value="100", min=0, max=1000) 58 | submitButton = wx.Button(parent=self, label="Submit") 59 | submitButton.Bind(wx.EVT_BUTTON, self.onSubmit) 60 | 61 | 62 | # add sizers to control layout of content 63 | self.mainSizer = wx.BoxSizer(wx.VERTICAL) # things will flow in vertical manner 64 | titleSizer = wx.BoxSizer(wx.HORIZONTAL) # sizer for title 65 | toolSizer = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label='Params') 66 | 67 | 68 | # add content to their respective sizer 69 | titleSizer.Add(title, proportion=0, flag=wx.ALL|wx.ALIGN_CENTER_VERTICAL, border=5) 70 | toolSizer.Add(muLabel, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) 71 | toolSizer.Add(self.muInput, 0, wx.ALL, 5) 72 | toolSizer.Add(stepsLabel, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) 73 | toolSizer.Add(self.stepsInput, 0, wx.ALL, 5) 74 | toolSizer.Add(submitButton, 0, wx.ALL, 5) 75 | 76 | self.mainSizer.Add(titleSizer, 0, wx.ALIGN_LEFT) 77 | self.mainSizer.Add(separator , 0, wx.ALL|wx.EXPAND, 5) 78 | self.mainSizer.Add(toolSizer, 0, wx.ALL|wx.CENTER, 5) 79 | 80 | # set main sizer; Sets the window to have the given layout sizer. 81 | self.SetSizer(self.mainSizer) 82 | self.mainSizer.Fit(self) # Sizes the window so that it fits around its subwindows. 83 | 84 | # include an additional sizer for embedding the plot 85 | plotSizer = wx.BoxSizer(wx.HORIZONTAL) 86 | self.p = CanvasFrame(self) 87 | plotSizer.Add(self.p, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5) 88 | self.mainSizer.Add(plotSizer, 0, wx.ALL|wx.CENTER|wx.ALIGN_CENTER, 5) 89 | self.Layout() 90 | 91 | 92 | def onSubmit(self, event): 93 | ''' 94 | On Submit, run the random walk module 95 | ''' 96 | mu = self.muInput.GetValue() 97 | steps = self.stepsInput.GetValue() 98 | demo = rw.RandomWalk(val=int(mu), steps=int(steps)) 99 | #demo.plot() 100 | self.p.plot(y=demo.y) 101 | self.Layout() 102 | 103 | 104 | 105 | class CanvasFrame(wx.Panel): 106 | def __init__(self, parent): 107 | super().__init__(parent=parent) 108 | 109 | self.figure = Figure(figsize=(6, 6), dpi=100) 110 | self.axes = self.figure.add_subplot(111) 111 | 112 | def plot(self, y, label='random walk'): 113 | self.axes.clear() # clear the axes before creating a new plot 114 | self.axes.plot(y) 115 | self.legend = self.axes.legend([label], shadow=True) 116 | #self.axes.margins(9.9) 117 | self.axes.set_ylabel('Y-label') 118 | self.axes.set_xlabel('X-label') 119 | self.axes.set_title('Title') 120 | self.axes.set_ylim(bottom=-10, top=10) 121 | 122 | self.canvas = FigureCanvas(self, -1, self.figure) 123 | 124 | self.sizer = wx.BoxSizer(wx.VERTICAL) 125 | self.sizer.Add(self.canvas, 1, wx.TOP | wx.CENTER | wx.EXPAND) 126 | 127 | self.SetSizer(self.sizer) 128 | self.Fit() 129 | 130 | 131 | 132 | if __name__ == "__main__": 133 | app = MyApp() 134 | app.MainLoop() 135 | -------------------------------------------------------------------------------- /Chapter04/MyButtonApp.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Reference: https://wiki.wxpython.org/BoxSizerTutorial 3 | ''' 4 | 5 | import wx 6 | 7 | 8 | class MyApp(wx.App): 9 | def __init__(self): 10 | super().__init__(clearSigInt=True) 11 | 12 | # init frame 13 | self.InitFrame() 14 | 15 | def InitFrame(self): 16 | frame = MyFrame() 17 | frame.Show() 18 | 19 | 20 | class MyFrame(wx.Frame): 21 | def __init__(self, title="MyButtonApp", pos=(100,100)): 22 | super().__init__(None, title=title, pos=pos) 23 | # initialize the frame's contents 24 | self.OnInit() 25 | 26 | def OnInit(self): 27 | self.panel = MyForm(self) 28 | self.Fit() 29 | 30 | class MyForm(wx.Panel): 31 | 32 | def __init__(self, parent): 33 | super().__init__(parent=parent) 34 | 35 | # Add a panel so it looks correct on all platforms 36 | 37 | # art provider provides basic art https://wxpython.org/Phoenix/docs/html/wx.ArtProvider.html 38 | bmp = wx.ArtProvider.GetBitmap(id=wx.ART_INFORMATION, 39 | client=wx.ART_OTHER, size=(16, 16)) 40 | titleIco = wx.StaticBitmap(self, wx.ID_ANY, bmp) 41 | title = wx.StaticText(self, wx.ID_ANY, 'My Title') 42 | 43 | inputOneIco = wx.StaticBitmap(self, wx.ID_ANY, bmp) 44 | labelOne = wx.StaticText(self, wx.ID_ANY, 'Input 1') 45 | self.inputTxtOne = wx.TextCtrl(self, wx.ID_ANY, value='Text box') 46 | 47 | inputTwoIco = wx.StaticBitmap(self, wx.ID_ANY, bmp) 48 | labelTwo = wx.StaticText(self, wx.ID_ANY, 'Input 2') 49 | # wx.SpinCtrl combines wx.TextCtrl and wx.SpinButton in one control. 50 | self.inputTwo = wx.SpinCtrl(self, wx.ID_ANY, value="0", min=0, max=100) 51 | 52 | inputThreeIco = wx.StaticBitmap(self, wx.ID_ANY, bmp) 53 | labelThree = wx.StaticText(self, wx.ID_ANY, 'Input 3') 54 | self.inputThree = wx.Choice(self, choices=['A', 'B', 'C']) 55 | 56 | 57 | inputFourIco = wx.StaticBitmap(self, wx.ID_ANY, bmp) 58 | labelFour = wx.StaticText(self, wx.ID_ANY, 'Input 4') 59 | self.inputFour1 = wx.CheckBox(parent=self, label="Choice 1") 60 | self.inputFour2 = wx.CheckBox(parent=self, label="Choice 2") 61 | self.inputFour3 = wx.CheckBox(parent=self, label="Choice 3") 62 | 63 | okBtn = wx.Button(self, wx.ID_ANY, 'OK') 64 | cancelBtn = wx.Button(self, wx.ID_ANY, 'Cancel') 65 | self.Bind(wx.EVT_BUTTON, self.onOK, okBtn) 66 | self.Bind(wx.EVT_BUTTON, self.onCancel, cancelBtn) 67 | 68 | mainSizer = wx.BoxSizer(wx.VERTICAL) 69 | titleSizer = wx.BoxSizer(wx.HORIZONTAL) 70 | inputOneSizer = wx.BoxSizer(wx.HORIZONTAL) 71 | inputTwoSizer = wx.BoxSizer(wx.HORIZONTAL) 72 | inputThreeSizer = wx.BoxSizer(wx.HORIZONTAL) 73 | inputFourSizer = wx.BoxSizer(wx.HORIZONTAL) 74 | submitBtnSizer = wx.BoxSizer(wx.HORIZONTAL) 75 | 76 | titleSizer.Add(titleIco, 0, wx.ALL, 5) 77 | titleSizer.Add(title, 0, wx.ALL, 5) 78 | 79 | inputOneSizer.Add(inputOneIco, 0, wx.ALL, 5) 80 | inputOneSizer.Add(labelOne, 0, wx.ALL, 5) 81 | 82 | inputOneSizer.Add(self.inputTxtOne, 1, wx.ALL|wx.EXPAND, 5) 83 | 84 | inputTwoSizer.Add(inputTwoIco, 0, wx.ALL, 5) 85 | inputTwoSizer.Add(labelTwo, 0, wx.ALL, 5) 86 | inputTwoSizer.Add(self.inputTwo, 1, wx.ALL|wx.EXPAND, 5) 87 | 88 | inputThreeSizer.Add(inputThreeIco, 0, wx.ALL, 5) 89 | inputThreeSizer.Add(labelThree, 0, wx.ALL, 5) 90 | inputThreeSizer.Add(self.inputThree, 1, wx.ALL|wx.EXPAND, 5) 91 | 92 | inputFourSizer.Add(inputFourIco, 0, wx.ALL, 5) 93 | inputFourSizer.Add(labelFour, 0, wx.ALL, 5) 94 | inputFourSizer.Add(self.inputFour1, 1, wx.ALL|wx.EXPAND, 5) 95 | inputFourSizer.Add(self.inputFour2, 1, wx.ALL|wx.EXPAND, 5) 96 | inputFourSizer.Add(self.inputFour3, 1, wx.ALL|wx.EXPAND, 5) 97 | 98 | submitBtnSizer.Add(okBtn, 0, wx.ALL, 5) 99 | submitBtnSizer.Add(cancelBtn, 0, wx.ALL, 5) 100 | 101 | mainSizer.Add(titleSizer, 0, wx.CENTER) 102 | mainSizer.Add(wx.StaticLine(self,), 0, wx.ALL|wx.EXPAND, 5) 103 | mainSizer.Add(inputOneSizer, 0, wx.ALL|wx.EXPAND, 5) 104 | mainSizer.Add(inputTwoSizer, 0, wx.ALL|wx.EXPAND, 5) 105 | mainSizer.Add(inputThreeSizer, 0, wx.ALL|wx.EXPAND, 5) 106 | mainSizer.Add(inputFourSizer, 0, wx.ALL|wx.EXPAND, 5) 107 | mainSizer.Add(wx.StaticLine(self), 0, wx.ALL|wx.EXPAND, 5) 108 | mainSizer.Add(submitBtnSizer, 0, wx.ALL|wx.CENTER, 5) 109 | 110 | self.SetSizer(mainSizer) 111 | mainSizer.Fit(self) 112 | self.Layout() 113 | 114 | 115 | def onOK(self, event): 116 | # Do something 117 | print('onOK handler') 118 | data = self.getData() 119 | print(data) 120 | 121 | def onCancel(self, event): 122 | self.closeProgram() 123 | 124 | def closeProgram(self): 125 | # self.GetParent() will get the frame which 126 | # has the .Close() method to close the program 127 | self.GetParent().Close() 128 | 129 | def getData(self): 130 | ''' 131 | this here will procure data from all buttons 132 | ''' 133 | data = [] 134 | data.append(self.inputTxtOne.GetValue()) 135 | data.append(self.inputTwo.GetValue()) 136 | selection = self.inputThree.GetSelection() 137 | data.append((selection, 138 | self.inputThree.GetString(selection)) 139 | ) 140 | data.append(self.inputFour1.GetValue()) 141 | data.append(self.inputFour2.GetValue()) 142 | data.append(self.inputFour3.GetValue()) 143 | return data 144 | 145 | # Run the program 146 | if __name__ == '__main__': 147 | app = MyApp() 148 | app.MainLoop() --------------------------------------------------------------------------------