├── .gitignore ├── README.md ├── recipe_10_catching_exceptions ├── error.log ├── exception_catcher.py ├── exception_decorator.py ├── exception_decorator2.py └── exception_decorator3.py ├── recipe_11_context_managers ├── builtin_context.py └── custom_context.py ├── recipe_12_converting_dates └── README.txt ├── recipe_13_about_box ├── main_classic.py └── main_phoenix.py ├── recipe_14_login_dialog ├── main_flag.py └── main_pubsub.py ├── recipe_15_dialog_from_config ├── config.ini └── main.py ├── recipe_16_saving_configs ├── controller.py ├── example.ini ├── images │ ├── cancel.png │ └── filesave.png └── main.py ├── recipe_17_binding_multiple_events └── main.py ├── recipe_18_firing_multiple_handlers └── main.py ├── recipe_19_get_event_name └── main.py ├── recipe_1_add_widgets_dynamically └── dynamic_widgets.py ├── recipe_20_key_char_events ├── char_events.py ├── key_events.py └── key_events2.py ├── recipe_21_drag_n_drop ├── drag_and_drop_app.py ├── file_drop_target.py ├── py_drop_target.py └── text_drop_target.py ├── recipe_22_drag_n_drop_file_to_os └── main.py ├── recipe_23_edit_gui_interactively ├── main.py └── testApp.py ├── recipe_24_extracting_xml_from_richtextctrl ├── main_classic.py └── main_phoenix.py ├── recipe_25_fade_in └── main.py ├── recipe_26_flashing_text ├── changing_text.py └── flashing_text.py ├── recipe_27_maximizing_frame ├── fullscreen.py └── maximize.py ├── recipe_28_frame_styles ├── default_frame.py ├── default_frame_2.py ├── default_frame_3.py ├── disabled_close_btn.py ├── no_caption.py ├── no_max_min.py ├── no_resize.py ├── no_system_menu.py └── stay_on_top.py ├── recipe_29_taskbar_icons ├── main_classic.py ├── main_phoenix.py └── python.ico ├── recipe_2_screenshots ├── main.py ├── myImage.png ├── screenshot.htm └── snapshotPrinter.py ├── recipe_30_minimize_to_tray ├── custTray.py ├── custTray_phoenix.py ├── main_classic.py ├── main_phoenix.py └── python.ico ├── recipe_31_children_from_sizers └── main.py ├── recipe_32_clipboard └── main.py ├── recipe_33_focus ├── acquire_focus.py ├── acquire_focus_2.py ├── focus_finder.py └── losing_focus.py ├── recipe_34_url_shortening ├── ars_example.py ├── ars_example_py3.py └── shortening_py2.py ├── recipe_35_using_objectlistview └── main.py ├── recipe_36_panel_destruction └── main.py ├── recipe_37_panel_switching └── main.py ├── recipe_38_pyplot ├── bar_graph.py ├── data.txt ├── plotting_25000_points.py ├── plotting_saved_data.py └── sin_cos.py ├── recipe_39_logging_textctrl └── main.py ├── recipe_3_embedding_image ├── custom_icon.py ├── image_from_exe.py ├── img_from_python_code.py ├── my_icon.py └── py.ico ├── recipe_40_redirect_stdout ├── main_non_thread_safe.py ├── main_non_thread_safe_phoenix.py └── main_thread_safe.py ├── recipe_41_simple_notebook ├── simple.py └── simple_refactored.py ├── recipe_42_singleton_frame └── main.py ├── recipe_43_storing_objects ├── objects_in_combobox.py └── objects_in_listbox.py ├── recipe_44_syncing_grid_scroll └── main.py ├── recipe_45_timers ├── multiple_timers.py ├── multiple_timers_2.py ├── simple_timer.py └── simple_timer_2.py ├── recipe_46_update_progress_thread ├── main_2.8.py └── main_3.0.py ├── recipe_47_wx_and_threads ├── main.py ├── main_legacy.py └── post_event_example.py ├── recipe_48_updating_your_app └── Releases │ ├── image_viewer-0.0.1 │ ├── main.py │ ├── mondrian.icns │ ├── mondrian.ico │ ├── setup.py │ └── version.py │ └── image_viewer-0.0.2 │ ├── main.py │ ├── mondrian.icns │ ├── mondrian.ico │ ├── setup.py │ └── version.py ├── recipe_49_xrc ├── login.py ├── login.xrc ├── notebook.xrc ├── notebook2.xrc ├── notebookXrcDemo.py ├── notebookXrcDemo2.py ├── panelOne.xrc └── panelTwo.xrc ├── recipe_4_background_image ├── big_cat.jpg ├── daniweb_example.py └── main.py ├── recipe_50_xrc_grid ├── broken_grid.py ├── grid.xrc └── working_grid.py ├── recipe_51_xrced ├── first_app.py ├── notebook.xrc ├── notebook_example.py ├── twoBtns.xrc ├── twoBtns_xrc.py └── twoBtns_xrc_subclass.py ├── recipe_52_centering_widgets ├── faux_spacers.py ├── nested_sizers.py └── stretch_spacer.py ├── recipe_53_widget_wrapping └── main.py ├── recipe_54_getting_selected_cells └── main.py ├── recipe_5_resetting_background_color └── main.py ├── recipe_6_dark_mode ├── __pycache__ │ └── dark_mode.cpython-35.pyc ├── dark_mode.py └── main.py ├── recipe_7_pubsub └── main.py ├── recipe_8_pydispatcher └── main.py └── recipe_9_disable_wizard_next ├── main_classic.py └── main_phoenix.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.wpr 2 | *.wpu 3 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wxPython Cookbook Code Examples 2 | 3 | The code examples for the book: **wxPython Cookbook** 4 | 5 | The book itself can be purchased through [Gumroad](http://gum.co/wxcookbook) or on [Leanpub](https://leanpub.com/wxpythoncookbook/). 6 | 7 | [](https://leanpub.com/wxpythoncookbook/) -------------------------------------------------------------------------------- /recipe_10_catching_exceptions/error.log: -------------------------------------------------------------------------------- 1 | 2016-11-23 14:36:01,869 - testLogger - Exception in onExcept: 2 | Traceback (most recent call last): 3 | File "/home/mdriscoll/py/wxcook/wxpythoncookbookcode/recipe_10_catching_exceptions/exception_decorator3_classic.py", line 20, in logger_func 4 | return func(*args) 5 | File "/home/mdriscoll/py/wxcook/wxpythoncookbookcode/recipe_10_catching_exceptions/exception_decorator3_classic.py", line 60, in onExcept 6 | 1/0 7 | ZeroDivisionError: integer division or modulo by zero 8 | 2016-12-04 20:28:37,165 - wxErrors - Exception 9 | Traceback (most recent call last): 10 | File "c:\Users\mike\Dropbox\Documents\wxpython_cookbook\wxpythoncookbookcode\recipe_10_catching_exceptions\exception_decorator2.py", line 20, in __call__ 11 | self.fn(self, *args, **kwargs) 12 | File "c:\Users\mike\Dropbox\Documents\wxpython_cookbook\wxpythoncookbookcode\recipe_10_catching_exceptions\exception_decorator2.py", line 40, in onExcept 13 | 1/0 14 | ZeroDivisionError: integer division or modulo by zero 15 | 2016-12-04 20:28:50,894 - testLogger - Exception in onExcept: 16 | Traceback (most recent call last): 17 | File "c:\Users\mike\Dropbox\Documents\wxpython_cookbook\wxpythoncookbookcode\recipe_10_catching_exceptions\exception_decorator3.py", line 20, in logger_func 18 | return func(*args) 19 | File "c:\Users\mike\Dropbox\Documents\wxpython_cookbook\wxpythoncookbookcode\recipe_10_catching_exceptions\exception_decorator3.py", line 60, in onExcept 20 | 1/0 21 | ZeroDivisionError: integer division or modulo by zero 22 | 2016-12-04 20:29:04,861 - wxErrors - Exception 23 | Traceback (most recent call last): 24 | File "c:\Users\mike\Dropbox\Documents\wxpython_cookbook\wxpythoncookbookcode\recipe_10_catching_exceptions\exception_decorator.py", line 22, in __call__ 25 | self.fn(self, evt) 26 | File "c:\Users\mike\Dropbox\Documents\wxpython_cookbook\wxpythoncookbookcode\recipe_10_catching_exceptions\exception_decorator.py", line 42, in onExcept 27 | 1/0 28 | ZeroDivisionError: integer division or modulo by zero 29 | -------------------------------------------------------------------------------- /recipe_10_catching_exceptions/exception_catcher.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import traceback 3 | import wx 4 | import wx.lib.agw.genericmessagedialog as GMD 5 | 6 | 7 | class Panel(wx.Panel): 8 | """""" 9 | 10 | def __init__(self, parent): 11 | """Constructor""" 12 | wx.Panel.__init__(self, parent) 13 | 14 | btn = wx.Button(self, label="Raise Exception") 15 | btn.Bind(wx.EVT_BUTTON, self.onExcept) 16 | 17 | def onExcept(self, event): 18 | """ 19 | Raise an error 20 | """ 21 | 1/0 22 | 23 | 24 | class Frame(wx.Frame): 25 | """""" 26 | 27 | def __init__(self): 28 | """Constructor""" 29 | wx.Frame.__init__(self, None, title="Exceptions") 30 | sys.excepthook = MyExceptionHook 31 | panel = Panel(self) 32 | self.Show() 33 | 34 | 35 | class ExceptionDialog(GMD.GenericMessageDialog): 36 | """ 37 | The dialog to show an exception 38 | """ 39 | 40 | def __init__(self, msg): 41 | """Constructor""" 42 | GMD.GenericMessageDialog.__init__(self, None, msg, "Exception!", 43 | wx.OK|wx.ICON_ERROR) 44 | 45 | 46 | def MyExceptionHook(etype, value, trace): 47 | """ 48 | Handler for all unhandled exceptions. 49 | 50 | :param `etype`: the exception type (`SyntaxError`, `ZeroDivisionError`, etc...); 51 | :type `etype`: `Exception` 52 | :param string `value`: the exception error message; 53 | :param string `trace`: the traceback header, if any (otherwise, it prints the 54 | standard Python header: ``Traceback (most recent call last)``. 55 | """ 56 | frame = wx.GetApp().GetTopWindow() 57 | tmp = traceback.format_exception(etype, value, trace) 58 | exception = "".join(tmp) 59 | 60 | dlg = ExceptionDialog(exception) 61 | dlg.ShowModal() 62 | dlg.Destroy() 63 | 64 | 65 | if __name__ == "__main__": 66 | app = wx.App(False) 67 | frame = Frame() 68 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_10_catching_exceptions/exception_decorator.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import wx 3 | 4 | 5 | class ExceptionLogging(object): 6 | 7 | def __init__(self, fn): 8 | self.fn = fn 9 | 10 | # create logging instance 11 | self.log = logging.getLogger("wxErrors") 12 | self.log.setLevel(logging.INFO) 13 | 14 | # create a logging file handler / formatter 15 | log_fh = logging.FileHandler("error.log") 16 | formatter = logging.Formatter("%(asctime)s - %(name)s - %(message)s") 17 | log_fh.setFormatter(formatter) 18 | self.log.addHandler(log_fh) 19 | 20 | def __call__(self, evt): 21 | try: 22 | self.fn(self, evt) 23 | except Exception as e: 24 | self.log.exception("Exception") 25 | 26 | 27 | class Panel(wx.Panel): 28 | """""" 29 | 30 | def __init__(self, parent): 31 | """Constructor""" 32 | wx.Panel.__init__(self, parent) 33 | 34 | btn = wx.Button(self, label="Raise Exception") 35 | btn.Bind(wx.EVT_BUTTON, self.onExcept) 36 | 37 | @ExceptionLogging 38 | def onExcept(self, event): 39 | """ 40 | Raise an error 41 | """ 42 | 1/0 43 | 44 | 45 | class Frame(wx.Frame): 46 | """""" 47 | 48 | def __init__(self): 49 | """Constructor""" 50 | wx.Frame.__init__(self, None, title="Exceptions") 51 | panel = Panel(self) 52 | self.Show() 53 | 54 | 55 | if __name__ == "__main__": 56 | app = wx.App(False) 57 | frame = Frame() 58 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_10_catching_exceptions/exception_decorator2.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import wx 3 | 4 | class ExceptionLogging(object): 5 | def __init__(self, fn, *args, **kwargs): 6 | self.fn = fn 7 | 8 | # create logging instance 9 | self.log = logging.getLogger("wxErrors") 10 | self.log.setLevel(logging.INFO) 11 | 12 | # create a logging file handler / formatter 13 | log_fh = logging.FileHandler("error.log") 14 | formatter = logging.Formatter("%(asctime)s - %(name)s - %(message)s") 15 | log_fh.setFormatter(formatter) 16 | self.log.addHandler(log_fh) 17 | 18 | def __call__(self, *args, **kwargs): 19 | try: 20 | self.fn(self, *args, **kwargs) 21 | except Exception as e: 22 | self.log.exception("Exception") 23 | 24 | 25 | class Panel(wx.Panel): 26 | """""" 27 | 28 | def __init__(self, parent): 29 | """Constructor""" 30 | wx.Panel.__init__(self, parent) 31 | 32 | btn = wx.Button(self, label="Raise Exception") 33 | btn.Bind(wx.EVT_BUTTON, self.onExcept) 34 | 35 | @ExceptionLogging 36 | def onExcept(self, event): 37 | """ 38 | Raise an error 39 | """ 40 | 1/0 41 | 42 | 43 | class Frame(wx.Frame): 44 | """""" 45 | 46 | def __init__(self): 47 | """Constructor""" 48 | wx.Frame.__init__(self, None, title="Exceptions") 49 | panel = Panel(self) 50 | self.Show() 51 | 52 | 53 | if __name__ == "__main__": 54 | app = wx.App(False) 55 | frame = Frame() 56 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_10_catching_exceptions/exception_decorator3.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import logging 4 | import wx 5 | 6 | print(wx.version()) 7 | 8 | def exceptionLogger(func, loggerName=''): 9 | """ 10 | A simple decorator that will catch and log any exceptions that may occur 11 | to the root logger. 12 | """ 13 | assert callable(func) 14 | mylogger = logging.getLogger(loggerName) 15 | 16 | # wrap a new function around the callable 17 | def logger_func(*args, **kw): 18 | try: 19 | if not kw: 20 | return func(*args) 21 | return func(*args, **kw) 22 | except Exception: 23 | mylogger.exception('Exception in %s:', func.__name__) 24 | 25 | logger_func.__name__ = func.__name__ 26 | logger_func.__doc__ = func.__doc__ 27 | if hasattr(func, '__dict__'): 28 | logger_func.__dict__.update(func.__dict__) 29 | return logger_func 30 | 31 | 32 | def exceptionLog2Logger(loggerName): 33 | """ 34 | A decorator that will catch and log any exceptions that may occur 35 | to the named logger. 36 | """ 37 | import functools 38 | return functools.partial(exceptionLogger, loggerName=loggerName) 39 | 40 | 41 | class Panel(wx.Panel): 42 | """""" 43 | 44 | def __init__(self, parent): 45 | """Constructor""" 46 | wx.Panel.__init__(self, parent) 47 | 48 | btn = wx.Button(self, label="Raise Exception") 49 | btn.Bind(wx.EVT_BUTTON, self.onExcept) 50 | 51 | @exceptionLog2Logger('testLogger') 52 | def onExcept(self, event): 53 | """ 54 | Raise an error 55 | """ 56 | print(self, event) 57 | print(isinstance(self, wx.Panel)) 58 | 59 | # trigger an exception 60 | 1/0 61 | 62 | 63 | class Frame(wx.Frame): 64 | """""" 65 | 66 | def __init__(self): 67 | """Constructor""" 68 | wx.Frame.__init__(self, None, title="Exceptions") 69 | panel = Panel(self) 70 | self.Show() 71 | 72 | 73 | if __name__ == "__main__": 74 | 75 | # set up the default logger 76 | log = logging.getLogger('testLogger') 77 | log.setLevel(logging.INFO) 78 | 79 | # create a logging file handler / formatter 80 | log_fh = logging.FileHandler("error.log") 81 | formatter = logging.Formatter("%(asctime)s - %(name)s - %(message)s") 82 | log_fh.setFormatter(formatter) 83 | log.addHandler(log_fh) 84 | 85 | app = wx.App(False) 86 | frame = Frame() 87 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_11_context_managers/builtin_context.py: -------------------------------------------------------------------------------- 1 | import time 2 | import wx 3 | 4 | 5 | class MyPanel(wx.Panel): 6 | """""" 7 | 8 | def __init__(self, parent): 9 | """Constructor""" 10 | wx.Panel.__init__(self, parent) 11 | self.frame = parent 12 | 13 | main_sizer = wx.BoxSizer(wx.VERTICAL) 14 | 15 | dlg_btn = wx.Button(self, label='Open ColorDialog') 16 | dlg_btn.Bind(wx.EVT_BUTTON, self.onOpenColorDialog) 17 | main_sizer.Add(dlg_btn, 0, wx.ALL|wx.CENTER) 18 | 19 | busy_btn = wx.Button(self, label='Open BusyInfo') 20 | busy_btn.Bind(wx.EVT_BUTTON, self.onOpenBusyInfo) 21 | main_sizer.Add(busy_btn,0, wx.ALL|wx.CENTER) 22 | 23 | self.SetSizer(main_sizer) 24 | 25 | def onOpenColorDialog(self, event): 26 | """ 27 | Creates and opens the wx.ColourDialog 28 | """ 29 | with wx.ColourDialog(self) as dlg: 30 | if dlg.ShowModal() == wx.ID_OK: 31 | data = dlg.GetColourData() 32 | color = str(data.GetColour().Get()) 33 | print 'You selected: %s\n' % color 34 | 35 | def onOpenBusyInfo(self, event): 36 | """ 37 | Creates and opens an instance of BusyInfo 38 | """ 39 | msg = 'This app is busy right now!' 40 | self.frame.Hide() 41 | with wx.BusyInfo(msg) as busy: 42 | time.sleep(5) 43 | self.frame.Show() 44 | 45 | 46 | class MyFrame(wx.Frame): 47 | """""" 48 | 49 | def __init__(self): 50 | """Constructor""" 51 | wx.Frame.__init__(self, None, title='Context Managers') 52 | panel = MyPanel(self) 53 | 54 | self.Show() 55 | 56 | 57 | if __name__ == '__main__': 58 | app = wx.App(False) 59 | frame = MyFrame() 60 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_11_context_managers/custom_context.py: -------------------------------------------------------------------------------- 1 | import os 2 | import wx 3 | 4 | 5 | class ContextFileDialog(wx.FileDialog): 6 | """""" 7 | 8 | def __enter__(self): 9 | """""" 10 | return self 11 | 12 | def __exit__(self, exc_type, exc_val, exc_tb): 13 | self.Destroy() 14 | 15 | 16 | class MyPanel(wx.Panel): 17 | """""" 18 | 19 | def __init__(self, parent): 20 | """Constructor""" 21 | wx.Panel.__init__(self, parent) 22 | 23 | btn = wx.Button(self, label='Open File') 24 | btn.Bind(wx.EVT_BUTTON, self.onOpenFile) 25 | 26 | def onOpenFile(self, event): 27 | """""" 28 | wildcard = "Python source (*.py)|*.py|" \ 29 | "All files (*.*)|*.*" 30 | kwargs = {'message':"Choose a file", 31 | 'defaultDir':os.path.dirname(os.path.abspath( __file__ )), 32 | 'defaultFile':"", 33 | 'wildcard':wildcard, 34 | 'style':wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR 35 | } 36 | with ContextFileDialog(self, **kwargs) as dlg: 37 | if dlg.ShowModal() == wx.ID_OK: 38 | paths = dlg.GetPaths() 39 | print "You chose the following file(s):" 40 | for path in paths: 41 | print path 42 | 43 | 44 | class MyFrame(wx.Frame): 45 | """""" 46 | 47 | def __init__(self): 48 | """Constructor""" 49 | wx.Frame.__init__(self, None, title='wxPython Contexts') 50 | panel = MyPanel(self) 51 | self.Show() 52 | 53 | 54 | if __name__ == '__main__': 55 | app = wx.App(False) 56 | frame = MyFrame() 57 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_12_converting_dates/README.txt: -------------------------------------------------------------------------------- 1 | This recipe doesn't have a complete runnable example, but you should be able to add the code from the recipe to your own code without issue. -------------------------------------------------------------------------------- /recipe_13_about_box/main_classic.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.html 3 | from wx.lib.wordwrap import wordwrap 4 | 5 | class MyForm(wx.Frame): 6 | 7 | def __init__(self): 8 | wx.Frame.__init__(self, None, wx.ID_ANY, title='The About Box') 9 | 10 | # Add a panel so it looks correct on all platforms 11 | self.panel = wx.Panel(self, wx.ID_ANY) 12 | 13 | # Create buttons 14 | aboutBtn = wx.Button(self.panel, wx.ID_ANY, "Open wx.AboutBox") 15 | self.Bind(wx.EVT_BUTTON, self.onAboutDlg, aboutBtn) 16 | aboutHtmlBtn = wx.Button(self.panel, wx.ID_ANY, "Open HtmlAboutBox") 17 | self.Bind(wx.EVT_BUTTON, self.onAboutHtmlDlg, aboutHtmlBtn) 18 | 19 | closeBtn = wx.Button(self.panel, wx.ID_ANY, "Close") 20 | self.Bind(wx.EVT_BUTTON, self.onClose, closeBtn) 21 | 22 | # Create Sizers 23 | topSizer = wx.BoxSizer(wx.VERTICAL) 24 | 25 | # Add widgets to sizers 26 | topSizer.Add(aboutBtn, 0, wx.ALL|wx.CENTER, 5) 27 | topSizer.Add(aboutHtmlBtn, 0, wx.ALL|wx.CENTER, 5) 28 | topSizer.Add(closeBtn, 0, wx.ALL|wx.CENTER, 5) 29 | 30 | # Create the menu 31 | self.createMenu() 32 | self.statusBar = self.CreateStatusBar() 33 | 34 | self.panel.SetSizer(topSizer) 35 | self.SetSizeHints(250,300,500,400) 36 | self.Fit() 37 | self.Refresh() 38 | 39 | def createMenu(self): 40 | """ Create the application's menu """ 41 | menubar = wx.MenuBar() 42 | 43 | # Create the file menu 44 | fileMenu = wx.Menu() 45 | 46 | # Append the close item 47 | # Append takes an id, the text label, and a string 48 | # to display in the statusbar when the item is selected 49 | close_menu_item = fileMenu.Append(wx.NewId(), 50 | "&Close", 51 | "Closes the application") 52 | # Bind an event to the menu item 53 | self.Bind(wx.EVT_MENU, self.onClose, close_menu_item) 54 | # Add the fileMenu to the menu bar 55 | menubar.Append(fileMenu, "&File") 56 | 57 | # Create the help menu 58 | helpMenu = wx.Menu() 59 | about_menu_item = helpMenu.Append(wx.NewId(), 60 | "&About", 61 | "Opens the About Box") 62 | self.Bind(wx.EVT_MENU, self.onAboutDlg, about_menu_item) 63 | menubar.Append(helpMenu, "&Help") 64 | 65 | # Add the menu bar to the frame 66 | self.SetMenuBar(menubar) 67 | 68 | def onAboutHtmlDlg(self, event): 69 | aboutDlg = AboutDlg(None) 70 | aboutDlg.Show() 71 | 72 | def onAboutDlg(self, event): 73 | info = wx.AboutDialogInfo() 74 | info.Name = "My About Box" 75 | info.Version = "0.0.1 Beta" 76 | info.Copyright = "(C) 2016 Python Geeks Everywhere" 77 | info.Description = wordwrap( 78 | "This is an example application that shows how to create " 79 | "different kinds of About Boxes using wxPython!", 80 | 350, wx.ClientDC(self.panel)) 81 | info.WebSite = ("http://www.pythonlibrary.org", "My Home Page") 82 | info.Developers = ["Mike Driscoll"] 83 | info.License = wordwrap("Completely and totally open source!", 500, 84 | wx.ClientDC(self.panel)) 85 | # Show the wx.AboutBox 86 | wx.AboutBox(info) 87 | 88 | def onClose(self, event): 89 | self.Close() 90 | 91 | 92 | class AboutDlg(wx.Frame): 93 | 94 | def __init__(self, parent): 95 | 96 | wx.Frame.__init__(self, parent, wx.ID_ANY, title="About", size=(400,400)) 97 | 98 | html = wxHTML(self) 99 | 100 | html.SetPage( 101 | '' 102 | 103 | "

About the About Tutorial

" 104 | 105 | "

This about box is for demo purposes only. It was created in June 2006 " 106 | 107 | "by Mike Driscoll.

" 108 | 109 | "

Software used in making this demo:

" 110 | 111 | '

Python 2.7 / 3.5

' 112 | 113 | '

wxPython 3.0.2.0 / Phoenix

' 114 | ) 115 | 116 | class wxHTML(wx.html.HtmlWindow): 117 | 118 | def OnLinkClicked(self, link): 119 | webbrowser.open(link.GetHref()) 120 | 121 | 122 | # Run the program 123 | if __name__ == '__main__': 124 | app = wx.App(False) 125 | frame = MyForm().Show() 126 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_13_about_box/main_phoenix.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.adv 3 | import wx.html 4 | from wx.lib.wordwrap import wordwrap 5 | 6 | 7 | class MyForm(wx.Frame): 8 | 9 | def __init__(self): 10 | wx.Frame.__init__(self, None, wx.ID_ANY, title='The About Box') 11 | 12 | # Add a panel so it looks correct on all platforms 13 | self.panel = wx.Panel(self, wx.ID_ANY) 14 | 15 | # Create buttons 16 | aboutBtn = wx.Button(self.panel, wx.ID_ANY, "Open wx.AboutBox") 17 | self.Bind(wx.EVT_BUTTON, self.onAboutDlg, aboutBtn) 18 | aboutHtmlBtn = wx.Button(self.panel, wx.ID_ANY, "Open HtmlAboutBox") 19 | self.Bind(wx.EVT_BUTTON, self.onAboutHtmlDlg, aboutHtmlBtn) 20 | 21 | closeBtn = wx.Button(self.panel, wx.ID_ANY, "Close") 22 | self.Bind(wx.EVT_BUTTON, self.onClose, closeBtn) 23 | 24 | # Create Sizers 25 | topSizer = wx.BoxSizer(wx.VERTICAL) 26 | 27 | # Add widgets to sizers 28 | topSizer.Add(aboutBtn, 0, wx.ALL|wx.CENTER, 5) 29 | topSizer.Add(aboutHtmlBtn, 0, wx.ALL|wx.CENTER, 5) 30 | topSizer.Add(closeBtn, 0, wx.ALL|wx.CENTER, 5) 31 | 32 | # Create the menu 33 | self.createMenu() 34 | self.statusBar = self.CreateStatusBar() 35 | 36 | self.panel.SetSizer(topSizer) 37 | self.SetSizeHints(250,300,500,400) 38 | self.Fit() 39 | self.Refresh() 40 | 41 | def createMenu(self): 42 | """ Create the application's menu """ 43 | menubar = wx.MenuBar() 44 | 45 | # Create the file menu 46 | fileMenu = wx.Menu() 47 | 48 | # Append the close item 49 | # Append takes an id, the text label, and a string 50 | # to display in the statusbar when the item is selected 51 | close_menu_item = fileMenu.Append(wx.NewId(), 52 | "&Close", 53 | "Closes the application") 54 | # Bind an event to the menu item 55 | self.Bind(wx.EVT_MENU, self.onClose, close_menu_item) 56 | # Add the fileMenu to the menu bar 57 | menubar.Append(fileMenu, "&File") 58 | 59 | # Create the help menu 60 | helpMenu = wx.Menu() 61 | about_menu_item = helpMenu.Append(wx.NewId(), 62 | "&About", 63 | "Opens the About Box") 64 | self.Bind(wx.EVT_MENU, self.onAboutDlg, about_menu_item) 65 | menubar.Append(helpMenu, "&Help") 66 | 67 | # Add the menu bar to the frame 68 | self.SetMenuBar(menubar) 69 | 70 | def onAboutHtmlDlg(self, event): 71 | aboutDlg = AboutDlg(None) 72 | aboutDlg.Show() 73 | 74 | def onAboutDlg(self, event): 75 | info = wx.adv.AboutDialogInfo() 76 | info.Name = "My About Box" 77 | info.Version = "0.0.1 Beta" 78 | info.Copyright = "(C) 2008 Python Geeks Everywhere" 79 | info.Description = wordwrap( 80 | "This is an example application that shows how to create " 81 | "different kinds of About Boxes using wxPython!", 82 | 350, wx.ClientDC(self.panel)) 83 | info.WebSite = ("http://www.pythonlibrary.org", "My Home Page") 84 | info.Developers = ["Mike Driscoll"] 85 | info.License = wordwrap("Completely and totally open source!", 500, 86 | wx.ClientDC(self.panel)) 87 | # Show the wx.AboutBox 88 | wx.adv.AboutBox(info) 89 | 90 | def onClose(self, event): 91 | self.Close() 92 | 93 | 94 | class AboutDlg(wx.Frame): 95 | 96 | def __init__(self, parent): 97 | 98 | wx.Frame.__init__(self, parent, wx.ID_ANY, title="About", size=(400,400)) 99 | 100 | html = wxHTML(self) 101 | 102 | html.SetPage( 103 | '' 104 | 105 | "

About the About Tutorial

" 106 | 107 | "

This about box is for demo purposes only. It was created in June 2006" 108 | 109 | "by Mike Driscoll.

" 110 | 111 | "

Software used in making this demo:

" 112 | 113 | '

Python 2.4

' 114 | 115 | '

wxPython 2.8

' 116 | ) 117 | 118 | class wxHTML(wx.html.HtmlWindow): 119 | 120 | def OnLinkClicked(self, link): 121 | webbrowser.open(link.GetHref()) 122 | 123 | 124 | # Run the program 125 | if __name__ == '__main__': 126 | app = wx.App(False) 127 | frame = MyForm().Show() 128 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_14_login_dialog/main_flag.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class LoginDialog(wx.Dialog): 5 | """ 6 | Class to define login dialog 7 | """ 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | wx.Dialog.__init__(self, None, title="Login") 12 | self.logged_in = False 13 | 14 | # user info 15 | user_sizer = wx.BoxSizer(wx.HORIZONTAL) 16 | 17 | user_lbl = wx.StaticText(self, label="Username:") 18 | user_sizer.Add(user_lbl, 0, wx.ALL|wx.CENTER, 5) 19 | self.user = wx.TextCtrl(self) 20 | user_sizer.Add(self.user, 0, wx.ALL, 5) 21 | 22 | # pass info 23 | p_sizer = wx.BoxSizer(wx.HORIZONTAL) 24 | 25 | p_lbl = wx.StaticText(self, label="Password:") 26 | p_sizer.Add(p_lbl, 0, wx.ALL|wx.CENTER, 5) 27 | self.password = wx.TextCtrl(self, style=wx.TE_PASSWORD|wx.TE_PROCESS_ENTER) 28 | self.password.Bind(wx.EVT_TEXT_ENTER, self.onLogin) 29 | p_sizer.Add(self.password, 0, wx.ALL, 5) 30 | 31 | main_sizer = wx.BoxSizer(wx.VERTICAL) 32 | main_sizer.Add(user_sizer, 0, wx.ALL, 5) 33 | main_sizer.Add(p_sizer, 0, wx.ALL, 5) 34 | 35 | btn = wx.Button(self, label="Login") 36 | btn.Bind(wx.EVT_BUTTON, self.onLogin) 37 | main_sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 38 | 39 | self.SetSizer(main_sizer) 40 | 41 | def onLogin(self, event): 42 | """ 43 | Check credentials and login 44 | """ 45 | stupid_password = "pa$$w0rd!" 46 | user_password = self.password.GetValue() 47 | if user_password == stupid_password: 48 | print("You are now logged in!") 49 | self.logged_in = True 50 | self.Close() 51 | else: 52 | print("Username or password is incorrect!") 53 | 54 | 55 | class MyPanel(wx.Panel): 56 | """""" 57 | 58 | def __init__(self, parent): 59 | """Constructor""" 60 | wx.Panel.__init__(self, parent) 61 | 62 | 63 | class MainFrame(wx.Frame): 64 | """""" 65 | 66 | def __init__(self): 67 | """Constructor""" 68 | wx.Frame.__init__(self, None, title="Main App") 69 | panel = MyPanel(self) 70 | 71 | # Ask user to login 72 | dlg = LoginDialog() 73 | dlg.ShowModal() 74 | authenticated = dlg.logged_in 75 | dlg.Destroy() 76 | if not authenticated: 77 | self.Close() 78 | 79 | self.Show() 80 | 81 | 82 | if __name__ == "__main__": 83 | app = wx.App(False) 84 | frame = MainFrame() 85 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_14_login_dialog/main_pubsub.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx.lib.pubsub import pub 3 | 4 | 5 | class LoginDialog(wx.Dialog): 6 | """ 7 | Class to define login dialog 8 | """ 9 | 10 | def __init__(self): 11 | """Constructor""" 12 | wx.Dialog.__init__(self, None, title="Login") 13 | 14 | # user info 15 | user_sizer = wx.BoxSizer(wx.HORIZONTAL) 16 | 17 | user_lbl = wx.StaticText(self, label="Username:") 18 | user_sizer.Add(user_lbl, 0, wx.ALL|wx.CENTER, 5) 19 | self.user = wx.TextCtrl(self) 20 | user_sizer.Add(self.user, 0, wx.ALL, 5) 21 | 22 | # pass info 23 | p_sizer = wx.BoxSizer(wx.HORIZONTAL) 24 | 25 | p_lbl = wx.StaticText(self, label="Password:") 26 | p_sizer.Add(p_lbl, 0, wx.ALL|wx.CENTER, 5) 27 | self.password = wx.TextCtrl(self, style=wx.TE_PASSWORD|wx.TE_PROCESS_ENTER) 28 | p_sizer.Add(self.password, 0, wx.ALL, 5) 29 | 30 | main_sizer = wx.BoxSizer(wx.VERTICAL) 31 | main_sizer.Add(user_sizer, 0, wx.ALL, 5) 32 | main_sizer.Add(p_sizer, 0, wx.ALL, 5) 33 | 34 | btn = wx.Button(self, label="Login") 35 | btn.Bind(wx.EVT_BUTTON, self.onLogin) 36 | main_sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 37 | 38 | self.SetSizer(main_sizer) 39 | 40 | def onLogin(self, event): 41 | """ 42 | Check credentials and login 43 | """ 44 | stupid_password = "pa$$w0rd!" 45 | user_password = self.password.GetValue() 46 | if user_password == stupid_password: 47 | print("You are now logged in!") 48 | pub.sendMessage("frameListener", message="show") 49 | self.Destroy() 50 | else: 51 | print("Username or password is incorrect!") 52 | 53 | 54 | class MyPanel(wx.Panel): 55 | """""" 56 | 57 | def __init__(self, parent): 58 | """Constructor""" 59 | wx.Panel.__init__(self, parent) 60 | 61 | 62 | class MainFrame(wx.Frame): 63 | """""" 64 | 65 | def __init__(self): 66 | """Constructor""" 67 | wx.Frame.__init__(self, None, title="Main App") 68 | panel = MyPanel(self) 69 | pub.subscribe(self.myListener, "frameListener") 70 | 71 | # Ask user to login 72 | dlg = LoginDialog() 73 | dlg.ShowModal() 74 | 75 | def myListener(self, message, arg2=None): 76 | """ 77 | Show the frame 78 | """ 79 | self.Show() 80 | 81 | 82 | if __name__ == "__main__": 83 | app = wx.App(False) 84 | frame = MainFrame() 85 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_15_dialog_from_config/config.ini: -------------------------------------------------------------------------------- 1 | [Labels] 2 | server = Update Server: 3 | username = Username: 4 | password = Password: 5 | update interval = Update Interval: 6 | agency = Agency Filter: 7 | filters = "" 8 | 9 | [Values] 10 | server = http://www.someCoolWebsite/hackery.php 11 | username = "" 12 | password = "" 13 | update interval = 2 14 | agency_choices = Include all agencies except, Include all agencies except, Exclude all agencies except 15 | filters = "" 16 | -------------------------------------------------------------------------------- /recipe_15_dialog_from_config/main.py: -------------------------------------------------------------------------------- 1 | import configobj 2 | import wx 3 | 4 | 5 | class PreferencesDialog(wx.Dialog): 6 | """ 7 | Creates and displays a preferences dialog that allows the user to 8 | change some settings. 9 | """ 10 | 11 | def __init__(self): 12 | """ 13 | Initialize the dialog 14 | """ 15 | wx.Dialog.__init__(self, None, title='Preferences', 16 | size=(550,300)) 17 | self.createWidgets() 18 | 19 | def createWidgets(self): 20 | """ 21 | Create and layout the widgets in the dialog 22 | """ 23 | lblSizer = wx.BoxSizer(wx.VERTICAL) 24 | valueSizer = wx.BoxSizer(wx.VERTICAL) 25 | btnSizer = wx.StdDialogButtonSizer() 26 | colSizer = wx.BoxSizer(wx.HORIZONTAL) 27 | mainSizer = wx.BoxSizer(wx.VERTICAL) 28 | 29 | iniFile = "config.ini" 30 | self.config = configobj.ConfigObj(iniFile) 31 | 32 | labels = self.config["Labels"] 33 | values = self.config["Values"] 34 | self.widgetNames = values 35 | font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD) 36 | 37 | for key in labels: 38 | value = labels[key] 39 | lbl = wx.StaticText(self, label=value) 40 | lbl.SetFont(font) 41 | lblSizer.Add(lbl, 0, wx.ALL, 5) 42 | 43 | for key in values: 44 | print(key) 45 | value = values[key] 46 | if isinstance(value, list): 47 | default = value[0] 48 | choices = value[1:] 49 | cbo = wx.ComboBox(self, value=value[0], 50 | size=wx.DefaultSize, choices=choices, 51 | style=wx.CB_DROPDOWN|wx.CB_READONLY, 52 | name=key) 53 | valueSizer.Add(cbo, 0, wx.ALL, 5) 54 | else: 55 | txt = wx.TextCtrl(self, value=value, name=key) 56 | valueSizer.Add(txt, 0, wx.ALL|wx.EXPAND, 5) 57 | 58 | saveBtn = wx.Button(self, wx.ID_OK, label="Save") 59 | saveBtn.Bind(wx.EVT_BUTTON, self.onSave) 60 | btnSizer.AddButton(saveBtn) 61 | 62 | cancelBtn = wx.Button(self, wx.ID_CANCEL) 63 | btnSizer.AddButton(cancelBtn) 64 | btnSizer.Realize() 65 | 66 | colSizer.Add(lblSizer) 67 | colSizer.Add(valueSizer, 1, wx.EXPAND) 68 | mainSizer.Add(colSizer, 0, wx.EXPAND) 69 | mainSizer.Add(btnSizer, 0, wx.ALL | wx.ALIGN_RIGHT, 5) 70 | self.SetSizer(mainSizer) 71 | 72 | def onSave(self, event): 73 | """ 74 | Saves values to disk 75 | """ 76 | for name in self.widgetNames: 77 | widget = wx.FindWindowByName(name) 78 | if isinstance(widget, wx.ComboBox): 79 | selection = widget.GetValue() 80 | choices = widget.GetItems() 81 | choices.insert(0, selection) 82 | self.widgetNames[name] = choices 83 | else: 84 | value = widget.GetValue() 85 | self.widgetNames[name] = value 86 | self.config.write() 87 | self.EndModal(0) 88 | 89 | 90 | class MyApp(wx.App): 91 | """""" 92 | 93 | def OnInit(self): 94 | """Constructor""" 95 | dlg = PreferencesDialog() 96 | dlg.ShowModal() 97 | dlg.Destroy() 98 | 99 | return True 100 | 101 | 102 | if __name__ == "__main__": 103 | app = MyApp(False) 104 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_16_saving_configs/controller.py: -------------------------------------------------------------------------------- 1 | # controller.py 2 | import configobj 3 | import os 4 | import sys 5 | 6 | 7 | appPath = os.path.abspath(os.path.dirname(os.path.join(sys.argv[0]))) 8 | inifile = os.path.join(appPath, "example.ini") 9 | 10 | def create_config(): 11 | """ 12 | Create the configuration file 13 | """ 14 | config = configobj.ConfigObj() 15 | config.filename = inifile 16 | config['update server'] = "http://www.someCoolWebsite/hackery.php" 17 | config['username'] = "" 18 | config['password'] = "" 19 | config['update interval'] = 2 20 | config['agency filter'] = 'include' 21 | config['filters'] = "" 22 | config.write() 23 | 24 | 25 | def get_config(): 26 | """ 27 | Open the config file and return a configobj 28 | """ 29 | if not os.path.exists(inifile): 30 | create_config() 31 | return configobj.ConfigObj(inifile) -------------------------------------------------------------------------------- /recipe_16_saving_configs/example.ini: -------------------------------------------------------------------------------- 1 | update server = http://www.someCoolWebsite/hackery.php 2 | username = "" 3 | password = "" 4 | update interval = 2 5 | agency filter = include 6 | filters = "" 7 | -------------------------------------------------------------------------------- /recipe_16_saving_configs/images/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_16_saving_configs/images/cancel.png -------------------------------------------------------------------------------- /recipe_16_saving_configs/images/filesave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_16_saving_configs/images/filesave.png -------------------------------------------------------------------------------- /recipe_17_binding_multiple_events/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyForm(wx.Frame): 5 | 6 | def __init__(self): 7 | wx.Frame.__init__( 8 | self, None, title="Binding Multiple Widgets") 9 | panel = wx.Panel(self, wx.ID_ANY) 10 | 11 | sizer = wx.BoxSizer(wx.VERTICAL) 12 | buttonOne = wx.Button(panel, label="One", name="one") 13 | buttonTwo = wx.Button(panel, label="Two", name="two") 14 | buttonThree = wx.Button(panel, label="Three", name="three") 15 | buttons = [buttonOne, buttonTwo, buttonThree] 16 | 17 | for button in buttons: 18 | self.buildButtons(button, sizer) 19 | 20 | panel.SetSizer(sizer) 21 | 22 | def buildButtons(self, btn, sizer): 23 | """""" 24 | btn.Bind(wx.EVT_BUTTON, self.onButton) 25 | sizer.Add(btn, 0, wx.ALL, 5) 26 | 27 | def onButton(self, event): 28 | """ 29 | This method is fired when its corresponding button is pressed 30 | """ 31 | button = event.GetEventObject() 32 | print("The button you pressed was labeled: " + button.GetLabel()) 33 | print("The button's name is " + button.GetName()) 34 | 35 | button_id = event.GetId() 36 | button_by_id = self.FindWindowById(button_id) 37 | print("The button you pressed was labeled: " + button_by_id.GetLabel()) 38 | print("The button's name is " + button_by_id.GetName()) 39 | 40 | 41 | if __name__ == "__main__": 42 | app = wx.App(False) 43 | frame = MyForm() 44 | frame.Show() 45 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_18_firing_multiple_handlers/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyPanel(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """Constructor""" 9 | wx.Panel.__init__(self, parent) 10 | btn = wx.Button(self, label="Press Me") 11 | btn.Bind(wx.EVT_BUTTON, self.HandlerOne) 12 | btn.Bind(wx.EVT_BUTTON, self.HandlerTwo) 13 | 14 | def HandlerOne(self, event): 15 | """""" 16 | print("handler one fired!") 17 | event.Skip() 18 | 19 | def HandlerTwo(self, event): 20 | """""" 21 | print("handler two fired!") 22 | event.Skip() 23 | 24 | 25 | class MyFrame(wx.Frame): 26 | """""" 27 | 28 | def __init__(self): 29 | """Constructor""" 30 | wx.Frame.__init__(self, None, title="Test") 31 | panel = MyPanel(self) 32 | self.Show() 33 | 34 | 35 | if __name__ == "__main__": 36 | app = wx.App(False) 37 | frame = MyFrame() 38 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_19_get_event_name/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.grid 3 | 4 | 5 | class MyForm(wx.Frame): 6 | 7 | def __init__(self): 8 | wx.Frame.__init__(self, None, title="Tutorial") 9 | 10 | self.eventDict = {} 11 | evt_names = [x for x in dir(wx) if x.startswith("EVT_")] 12 | for name in evt_names: 13 | evt = getattr(wx, name) 14 | if isinstance(evt, wx.PyEventBinder): 15 | self.eventDict[evt.typeId] = name 16 | 17 | grid_evt_names = [x for x in dir(wx.grid) if x.startswith("EVT_")] 18 | for name in grid_evt_names: 19 | evt = getattr(wx.grid, name) 20 | if isinstance(evt, wx.PyEventBinder): 21 | self.eventDict[evt.typeId] = name 22 | 23 | panel = wx.Panel(self, wx.ID_ANY) 24 | btn = wx.Button(panel, wx.ID_ANY, "Get POS") 25 | 26 | btn.Bind(wx.EVT_BUTTON, self.onEvent) 27 | panel.Bind(wx.EVT_LEFT_DCLICK, self.onEvent) 28 | panel.Bind(wx.EVT_RIGHT_DOWN, self.onEvent) 29 | 30 | def onEvent(self, event): 31 | """ 32 | Print out what event was fired 33 | """ 34 | evt_id = event.GetEventType() 35 | print(self.eventDict[evt_id]) 36 | 37 | 38 | if __name__ == "__main__": 39 | app = wx.App(redirect=True) 40 | frame = MyForm().Show() 41 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_1_add_widgets_dynamically/dynamic_widgets.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyPanel(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """Constructor""" 9 | wx.Panel.__init__(self, parent) 10 | self.number_of_buttons = 0 11 | self.frame = parent 12 | 13 | self.mainSizer = wx.BoxSizer(wx.VERTICAL) 14 | controlSizer = wx.BoxSizer(wx.HORIZONTAL) 15 | self.widgetSizer = wx.BoxSizer(wx.VERTICAL) 16 | 17 | self.addButton = wx.Button(self, label="Add") 18 | self.addButton.Bind(wx.EVT_BUTTON, self.onAddWidget) 19 | controlSizer.Add(self.addButton, 0, wx.CENTER|wx.ALL, 5) 20 | 21 | self.removeButton = wx.Button(self, label="Remove") 22 | self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveWidget) 23 | controlSizer.Add(self.removeButton, 0, wx.CENTER|wx.ALL, 5) 24 | 25 | self.mainSizer.Add(controlSizer, 0, wx.CENTER) 26 | self.mainSizer.Add(self.widgetSizer, 0, wx.CENTER|wx.ALL, 10) 27 | 28 | self.SetSizer(self.mainSizer) 29 | 30 | def onAddWidget(self, event): 31 | """""" 32 | self.number_of_buttons += 1 33 | label = "Button %s" % self.number_of_buttons 34 | name = "button%s" % self.number_of_buttons 35 | new_button = wx.Button(self, label=label, name=name) 36 | self.widgetSizer.Add(new_button, 0, wx.ALL, 5) 37 | self.frame.fSizer.Layout() 38 | self.frame.Fit() 39 | 40 | def onRemoveWidget(self, event): 41 | """""" 42 | if self.widgetSizer.GetChildren(): 43 | self.widgetSizer.Hide(self.number_of_buttons-1) 44 | self.widgetSizer.Remove(self.number_of_buttons-1) 45 | self.number_of_buttons -= 1 46 | self.frame.fSizer.Layout() 47 | self.frame.Fit() 48 | 49 | 50 | class MyFrame(wx.Frame): 51 | """""" 52 | 53 | def __init__(self): 54 | """Constructor""" 55 | wx.Frame.__init__(self, parent=None, title="Add / Remove Buttons") 56 | self.fSizer = wx.BoxSizer(wx.VERTICAL) 57 | panel = MyPanel(self) 58 | self.fSizer.Add(panel, 1, wx.EXPAND) 59 | self.SetSizer(self.fSizer) 60 | self.Fit() 61 | self.Show() 62 | 63 | 64 | if __name__ == "__main__": 65 | app = wx.App(False) 66 | frame = MyFrame() 67 | app.MainLoop() 68 | -------------------------------------------------------------------------------- /recipe_20_key_char_events/char_events.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title="Char Event Tutorial") 7 | 8 | # Add a panel so it looks the correct on all platforms 9 | panel = wx.Panel(self, wx.ID_ANY) 10 | btn = wx.TextCtrl(panel, value="") 11 | 12 | btn.Bind(wx.EVT_CHAR, self.onCharEvent) 13 | 14 | def onCharEvent(self, event): 15 | keycode = event.GetKeyCode() 16 | controlDown = event.CmdDown() 17 | altDown = event.AltDown() 18 | shiftDown = event.ShiftDown() 19 | 20 | print(keycode) 21 | if keycode == wx.WXK_SPACE: 22 | print("you pressed the spacebar!") 23 | elif controlDown and altDown: 24 | print(keycode) 25 | event.Skip() 26 | 27 | 28 | if __name__ == "__main__": 29 | app = wx.App(True) 30 | frame = MyForm() 31 | frame.Show() 32 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_20_key_char_events/key_events.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title="Key Press Tutorial") 7 | 8 | panel = wx.Panel(self, wx.ID_ANY) 9 | btn = wx.Button(panel, label="OK") 10 | 11 | btn.Bind(wx.EVT_KEY_DOWN, self.onKeyPress) 12 | 13 | def onKeyPress(self, event): 14 | keycode = event.GetKeyCode() 15 | print(keycode) 16 | if keycode == wx.WXK_SPACE: 17 | print("you pressed the spacebar!") 18 | event.Skip() 19 | 20 | 21 | if __name__ == "__main__": 22 | app = wx.App(True) 23 | frame = MyForm() 24 | frame.Show() 25 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_20_key_char_events/key_events2.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title="Key Press Tutorial 2") 7 | 8 | panel = wx.Panel(self, wx.ID_ANY) 9 | sizer = wx.BoxSizer(wx.VERTICAL) 10 | 11 | btn = self.onWidgetSetup(wx.Button(panel, label="OK"), 12 | wx.EVT_KEY_UP, 13 | self.onButtonKeyEvent, sizer) 14 | txt = self.onWidgetSetup(wx.TextCtrl(panel, value=""), 15 | wx.EVT_KEY_DOWN, self.onTextKeyEvent, 16 | sizer) 17 | panel.SetSizer(sizer) 18 | 19 | def onWidgetSetup(self, widget, event, handler, sizer): 20 | widget.Bind(event, handler) 21 | sizer.Add(widget, 0, wx.ALL, 5) 22 | return widget 23 | 24 | def onButtonKeyEvent(self, event): 25 | keycode = event.GetKeyCode() 26 | print(keycode) 27 | if keycode == wx.WXK_SPACE: 28 | print("you pressed the spacebar!") 29 | event.Skip() 30 | 31 | def onTextKeyEvent(self, event): 32 | keycode = event.GetKeyCode() 33 | print(keycode) 34 | if keycode == wx.WXK_DELETE: 35 | print("you pressed the delete key!") 36 | event.Skip() 37 | 38 | 39 | if __name__ == "__main__": 40 | app = wx.App(True) 41 | frame = MyForm() 42 | frame.Show() 43 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_21_drag_n_drop/drag_and_drop_app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import stat 3 | import time 4 | import wx 5 | from ObjectListView import ObjectListView, ColumnDefn 6 | 7 | 8 | class MyFileDropTarget(wx.FileDropTarget): 9 | """""" 10 | 11 | def __init__(self, window): 12 | """Constructor""" 13 | wx.FileDropTarget.__init__(self) 14 | self.window = window 15 | 16 | def OnDropFiles(self, x, y, filenames): 17 | """ 18 | When files are dropped, update the display 19 | """ 20 | self.window.updateDisplay(filenames) 21 | return True 22 | 23 | 24 | class FileInfo(object): 25 | """""" 26 | 27 | def __init__(self, path, date_created, date_modified, size): 28 | """Constructor""" 29 | self.name = os.path.basename(path) 30 | self.path = path 31 | self.date_created = date_created 32 | self.date_modified = date_modified 33 | self.size = size 34 | 35 | 36 | class MainPanel(wx.Panel): 37 | """""" 38 | 39 | def __init__(self, parent): 40 | """Constructor""" 41 | wx.Panel.__init__(self, parent=parent) 42 | self.file_list = [] 43 | 44 | file_drop_target = MyFileDropTarget(self) 45 | self.olv = ObjectListView( 46 | self, style=wx.LC_REPORT|wx.SUNKEN_BORDER) 47 | self.olv.SetDropTarget(file_drop_target) 48 | self.setFiles() 49 | 50 | sizer = wx.BoxSizer(wx.VERTICAL) 51 | sizer.Add(self.olv, 1, wx.EXPAND) 52 | self.SetSizer(sizer) 53 | 54 | def updateDisplay(self, file_list): 55 | """""" 56 | for path in file_list: 57 | file_stats = os.stat(path) 58 | creation_time = time.strftime( 59 | "%m/%d/%Y %I:%M %p", 60 | time.localtime(file_stats[stat.ST_CTIME])) 61 | modified_time = time.strftime( 62 | "%m/%d/%Y %I:%M %p", 63 | time.localtime(file_stats[stat.ST_MTIME])) 64 | file_size = file_stats[stat.ST_SIZE] 65 | if file_size > 1024: 66 | file_size = file_size / 1024.0 67 | file_size = "%.2f KB" % file_size 68 | 69 | self.file_list.append(FileInfo(path, 70 | creation_time, 71 | modified_time, 72 | file_size)) 73 | 74 | self.olv.SetObjects(self.file_list) 75 | 76 | def setFiles(self): 77 | """""" 78 | self.olv.SetColumns([ 79 | ColumnDefn("Name", "left", 220, "name"), 80 | ColumnDefn("Date created", "left", 150, "date_created"), 81 | ColumnDefn("Date modified", "left", 150, "date_modified"), 82 | ColumnDefn("Size", "left", 100, "size") 83 | ]) 84 | self.olv.SetObjects(self.file_list) 85 | 86 | 87 | class MainFrame(wx.Frame): 88 | """""" 89 | 90 | def __init__(self): 91 | """Constructor""" 92 | wx.Frame.__init__(self, None, 93 | title="OLV DnD Tutorial", size=(800,600)) 94 | panel = MainPanel(self) 95 | self.Show() 96 | 97 | 98 | def main(): 99 | """""" 100 | app = wx.App(False) 101 | frame = MainFrame() 102 | app.MainLoop() 103 | 104 | 105 | if __name__ == "__main__": 106 | main() -------------------------------------------------------------------------------- /recipe_21_drag_n_drop/file_drop_target.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyFileDropTarget(wx.FileDropTarget): 5 | """""" 6 | 7 | def __init__(self, window): 8 | """Constructor""" 9 | wx.FileDropTarget.__init__(self) 10 | self.window = window 11 | 12 | def OnDropFiles(self, x, y, filenames): 13 | """ 14 | When files are dropped, write where they were dropped and then 15 | the file paths themselves 16 | """ 17 | self.window.SetInsertionPointEnd() 18 | self.window.updateText("\n%d file(s) dropped at %d,%d:\n" % 19 | (len(filenames), x, y)) 20 | for filepath in filenames: 21 | self.window.updateText(filepath + '\n') 22 | 23 | return True 24 | 25 | 26 | class DnDPanel(wx.Panel): 27 | """""" 28 | 29 | def __init__(self, parent): 30 | """Constructor""" 31 | wx.Panel.__init__(self, parent=parent) 32 | 33 | file_drop_target = MyFileDropTarget(self) 34 | lbl = wx.StaticText(self, label="Drag some files here:") 35 | self.fileTextCtrl = wx.TextCtrl(self, 36 | style=wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY) 37 | self.fileTextCtrl.SetDropTarget(file_drop_target) 38 | 39 | sizer = wx.BoxSizer(wx.VERTICAL) 40 | sizer.Add(lbl, 0, wx.ALL, 5) 41 | sizer.Add(self.fileTextCtrl, 1, wx.EXPAND|wx.ALL, 5) 42 | self.SetSizer(sizer) 43 | 44 | def SetInsertionPointEnd(self): 45 | """ 46 | Put insertion point at end of text control to prevent overwriting 47 | """ 48 | self.fileTextCtrl.SetInsertionPointEnd() 49 | 50 | def updateText(self, text): 51 | """ 52 | Write text to the text control 53 | """ 54 | self.fileTextCtrl.WriteText(text) 55 | 56 | 57 | class DnDFrame(wx.Frame): 58 | """""" 59 | 60 | def __init__(self): 61 | """Constructor""" 62 | wx.Frame.__init__(self, parent=None, title="DnD Tutorial") 63 | panel = DnDPanel(self) 64 | self.Show() 65 | 66 | 67 | if __name__ == "__main__": 68 | app = wx.App(False) 69 | frame = DnDFrame() 70 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_21_drag_n_drop/py_drop_target.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyURLDropTarget(wx.PyDropTarget): 5 | 6 | def __init__(self, window): 7 | wx.PyDropTarget.__init__(self) 8 | self.window = window 9 | 10 | self.data = wx.URLDataObject(); 11 | self.SetDataObject(self.data) 12 | 13 | def OnDragOver(self, x, y, d): 14 | return wx.DragLink 15 | 16 | def OnData(self, x, y, d): 17 | if not self.GetData(): 18 | return wx.DragNone 19 | 20 | url = self.data.GetURL() 21 | self.window.AppendText(url + "\n") 22 | 23 | return d 24 | 25 | 26 | class DnDPanel(wx.Panel): 27 | """""" 28 | 29 | def __init__(self, parent): 30 | """Constructor""" 31 | wx.Panel.__init__(self, parent=parent) 32 | font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False) 33 | 34 | # create and setup first set of widgets 35 | lbl = wx.StaticText(self, 36 | label="Drag some URLS from your browser here:") 37 | lbl.SetFont(font) 38 | self.dropText = wx.TextCtrl( 39 | self, size=(200,200), 40 | style=wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY) 41 | dt = MyURLDropTarget(self.dropText) 42 | self.dropText.SetDropTarget(dt) 43 | firstSizer = self.addWidgetsToSizer([lbl, self.dropText]) 44 | 45 | # create and setup second set of widgets 46 | lbl = wx.StaticText(self, label="Drag this URL to your browser:") 47 | lbl.SetFont(font) 48 | self.draggableURLText = wx.TextCtrl(self, 49 | value="http://www.mousevspython.com") 50 | self.draggableURLText.Bind(wx.EVT_MOTION, self.OnStartDrag) 51 | secondSizer = self.addWidgetsToSizer([lbl, self.draggableURLText]) 52 | 53 | # Add sizers to main sizer 54 | mainSizer = wx.BoxSizer(wx.VERTICAL) 55 | mainSizer.Add(firstSizer, 0, wx.EXPAND) 56 | mainSizer.Add(secondSizer, 0, wx.EXPAND) 57 | self.SetSizer(mainSizer) 58 | 59 | def addWidgetsToSizer(self, widgets): 60 | """ 61 | Returns a sizer full of widgets 62 | """ 63 | sizer = wx.BoxSizer(wx.HORIZONTAL) 64 | for widget in widgets: 65 | if isinstance(widget, wx.TextCtrl): 66 | sizer.Add(widget, 1, wx.EXPAND|wx.ALL, 5) 67 | else: 68 | sizer.Add(widget, 0, wx.ALL, 5) 69 | return sizer 70 | 71 | def OnStartDrag(self, evt): 72 | """""" 73 | if evt.Dragging(): 74 | url = self.draggableURLText.GetValue() 75 | data = wx.URLDataObject() 76 | data.SetURL(url) 77 | 78 | dropSource = wx.DropSource(self.draggableURLText) 79 | dropSource.SetData(data) 80 | result = dropSource.DoDragDrop() 81 | 82 | 83 | class DnDFrame(wx.Frame): 84 | """""" 85 | 86 | def __init__(self): 87 | """Constructor""" 88 | wx.Frame.__init__(self, parent=None, 89 | title="DnD URL Tutorial", size=(800,600)) 90 | panel = DnDPanel(self) 91 | self.Show() 92 | 93 | 94 | if __name__ == "__main__": 95 | app = wx.App(False) 96 | frame = DnDFrame() 97 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_21_drag_n_drop/text_drop_target.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyTextDropTarget(wx.TextDropTarget): 5 | 6 | def __init__(self, textctrl): 7 | wx.TextDropTarget.__init__(self) 8 | self.textctrl = textctrl 9 | 10 | def OnDropText(self, x, y, text): 11 | self.textctrl.WriteText("(%d, %d)\n%s\n" % (x, y, text)) 12 | return True 13 | 14 | def OnDragOver(self, x, y, d): 15 | return wx.DragCopy 16 | 17 | 18 | class DnDPanel(wx.Panel): 19 | """""" 20 | 21 | def __init__(self, parent): 22 | """Constructor""" 23 | wx.Panel.__init__(self, parent=parent) 24 | 25 | 26 | lbl = wx.StaticText(self, label="Drag some text here:") 27 | self.myTextCtrl = wx.TextCtrl( 28 | self, style=wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY) 29 | text_dt = MyTextDropTarget(self.myTextCtrl) 30 | self.myTextCtrl.SetDropTarget(text_dt) 31 | 32 | sizer = wx.BoxSizer(wx.VERTICAL) 33 | sizer.Add(self.myTextCtrl, 1, wx.EXPAND) 34 | self.SetSizer(sizer) 35 | 36 | def WriteText(self, text): 37 | self.text.WriteText(text) 38 | 39 | 40 | class DnDFrame(wx.Frame): 41 | """""" 42 | 43 | def __init__(self): 44 | """Constructor""" 45 | wx.Frame.__init__( 46 | self, parent=None, title="DnD Text Tutorial") 47 | panel = DnDPanel(self) 48 | self.Show() 49 | 50 | 51 | if __name__ == "__main__": 52 | app = wx.App(False) 53 | frame = DnDFrame() 54 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_22_drag_n_drop_file_to_os/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import os 3 | import time 4 | 5 | 6 | class MyListCtrl(wx.ListCtrl): 7 | 8 | def __init__(self, parent, id): 9 | wx.ListCtrl.__init__(self, parent, id, 10 | style=wx.LC_REPORT) 11 | 12 | files = os.listdir('.') 13 | 14 | self.InsertColumn(0, 'Name') 15 | self.InsertColumn(1, 'Ext') 16 | self.InsertColumn(2, 'Size', 17 | wx.LIST_FORMAT_RIGHT) 18 | self.InsertColumn(3, 'Modified') 19 | 20 | self.SetColumnWidth(0, 220) 21 | self.SetColumnWidth(1, 70) 22 | self.SetColumnWidth(2, 100) 23 | self.SetColumnWidth(3, 420) 24 | 25 | j = 0 26 | for i in files: 27 | (name, ext) = os.path.splitext(i) 28 | 29 | size = os.path.getsize(i) 30 | sec = os.path.getmtime(i) 31 | self.InsertStringItem(j, "{}{}".format(name, ext)) 32 | self.SetStringItem(j, 1, ext) 33 | self.SetStringItem(j, 2, str(size) + ' B') 34 | self.SetStringItem( 35 | j, 3, time.strftime('%Y-%m-%d %H:%M', 36 | time.localtime(sec))) 37 | 38 | if os.path.isdir(i): 39 | self.SetItemImage(j, 1) 40 | elif 'py' in ext: 41 | self.SetItemImage(j, 2) 42 | elif 'jpg' in ext: 43 | self.SetItemImage(j, 3) 44 | elif 'pdf' in ext: 45 | self.SetItemImage(j, 4) 46 | else: 47 | self.SetItemImage(j, 0) 48 | 49 | if (j % 2) == 0: 50 | self.SetItemBackgroundColour(j, 'light blue') 51 | j = j + 1 52 | 53 | 54 | class DnDFrame(wx.Frame): 55 | 56 | def __init__(self): 57 | wx.Frame.__init__(self, None, title='DnD Files') 58 | panel = wx.Panel(self) 59 | 60 | p1 = MyListCtrl(panel, -1) 61 | p1.Bind(wx.EVT_LIST_BEGIN_DRAG, self.onDrag) 62 | sizer = wx.BoxSizer() 63 | sizer.Add(p1, 1, wx.EXPAND) 64 | panel.SetSizer(sizer) 65 | 66 | self.Center() 67 | self.Show(True) 68 | 69 | 70 | def onDrag(self, event): 71 | """""" 72 | data = wx.FileDataObject() 73 | obj = event.GetEventObject() 74 | id = event.GetIndex() 75 | filename = obj.GetItem(id).GetText() 76 | dirname = os.path.dirname(os.path.abspath( 77 | os.listdir(".")[0])) 78 | fullpath = os.path.join(dirname, filename) 79 | 80 | data.AddFile(fullpath) 81 | 82 | dropSource = wx.DropSource(obj) 83 | dropSource.SetData(data) 84 | result = dropSource.DoDragDrop() 85 | print(fullpath) 86 | 87 | if __name__ == '__main__': 88 | app = wx.App(False) 89 | frame = DnDFrame() 90 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_23_edit_gui_interactively/main.py: -------------------------------------------------------------------------------- 1 | # main.py 2 | import testApp 3 | import wx 4 | 5 | 6 | class ReloaderPanel(wx.Panel): 7 | """""" 8 | 9 | def __init__(self, parent): 10 | """Constructor""" 11 | wx.Panel.__init__(self, parent) 12 | self.testFrame = None 13 | 14 | showAppBtn = wx.Button(self, label="Show App") 15 | showAppBtn.Bind(wx.EVT_BUTTON, self.onShowApp) 16 | 17 | reloadBtn = wx.Button(self, label="Reload") 18 | reloadBtn.Bind(wx.EVT_BUTTON, self.onReload) 19 | 20 | mainSizer = wx.BoxSizer(wx.VERTICAL) 21 | mainSizer.Add(showAppBtn, 0, wx.ALL|wx.CENTER, 5) 22 | mainSizer.Add(reloadBtn, 0, wx.ALL|wx.CENTER, 5) 23 | self.SetSizer(mainSizer) 24 | 25 | def onReload(self, event): 26 | """ 27 | Reload the code! 28 | """ 29 | if self.testFrame: 30 | self.testFrame.Close() 31 | try: 32 | reload(testApp) 33 | except NameError: 34 | # reload doesn't exist in Python 3. 35 | # Use importlib.reload in Python 3.4+ 36 | # or imp.reload in Python 3.0 - 3.3 37 | import importlib 38 | importlib.reload(testApp) 39 | self.showApp() 40 | else: 41 | self.testFrame = None 42 | 43 | def onShowApp(self, event): 44 | """ 45 | Call the showApp() method 46 | """ 47 | self.showApp() 48 | 49 | def showApp(self): 50 | """ 51 | Show the application we want to edit dynamically 52 | """ 53 | self.testFrame = testApp.TestFrame() 54 | 55 | 56 | class ReloaderFrame(wx.Frame): 57 | """""" 58 | 59 | def __init__(self): 60 | """Constructor""" 61 | wx.Frame.__init__(self, None, title="Reloader") 62 | panel = ReloaderPanel(self) 63 | self.Show() 64 | 65 | 66 | if __name__ == "__main__": 67 | app = wx.App(False) 68 | frame = ReloaderFrame() 69 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_23_edit_gui_interactively/testApp.py: -------------------------------------------------------------------------------- 1 | # testApp.py 2 | import wx 3 | 4 | 5 | class TestPanel(wx.Panel): 6 | """""" 7 | 8 | def __init__(self, parent): 9 | """Constructor""" 10 | wx.Panel.__init__(self, parent) 11 | btn = wx.Button(self, label='Test') 12 | 13 | 14 | class TestFrame(wx.Frame): 15 | """""" 16 | 17 | def __init__(self): 18 | """Constructor""" 19 | wx.Frame.__init__(self, None, title="Test program") 20 | panel = TestPanel(self) 21 | self.Show() 22 | 23 | 24 | if __name__ == "__main__": 25 | app = wx.App(False) 26 | frame = TestFrame() 27 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_24_extracting_xml_from_richtextctrl/main_classic.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.richtext 3 | 4 | from StringIO import StringIO 5 | 6 | 7 | class MyFrame(wx.Frame): 8 | 9 | def __init__(self): 10 | wx.Frame.__init__(self, None, title='Richtext Test') 11 | 12 | sizer = wx.BoxSizer(wx.VERTICAL) 13 | self.rt = wx.richtext.RichTextCtrl(self) 14 | self.rt.SetMinSize((300,200)) 15 | 16 | save_button = wx.Button(self, label="Save") 17 | save_button.Bind(wx.EVT_BUTTON, self.on_save) 18 | 19 | sizer = wx.BoxSizer(wx.VERTICAL) 20 | sizer.Add(self.rt, 1, wx.EXPAND|wx.ALL, 6) 21 | sizer.Add(save_button, 0, wx.EXPAND|wx.ALL, 6) 22 | 23 | self.SetSizer(sizer) 24 | self.Show() 25 | 26 | def on_save(self, event): 27 | out = StringIO() 28 | handler = wx.richtext.RichTextXMLHandler() 29 | rt_buffer = self.rt.GetBuffer() 30 | handler.SaveStream(rt_buffer, out) 31 | self.xml_content = out.getvalue() 32 | print(self.xml_content) 33 | 34 | 35 | if __name__ == "__main__": 36 | app = wx.App(False) 37 | frame = MyFrame() 38 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_24_extracting_xml_from_richtextctrl/main_phoenix.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.richtext 3 | 4 | from io import BytesIO 5 | 6 | 7 | class MyFrame(wx.Frame): 8 | 9 | def __init__(self): 10 | wx.Frame.__init__(self, None, title='Richtext Test') 11 | 12 | sizer = wx.BoxSizer(wx.VERTICAL) 13 | self.rt = wx.richtext.RichTextCtrl(self) 14 | self.rt.SetMinSize((300,200)) 15 | 16 | save_button = wx.Button(self, label="Save") 17 | save_button.Bind(wx.EVT_BUTTON, self.on_save) 18 | 19 | sizer = wx.BoxSizer(wx.VERTICAL) 20 | sizer.Add(self.rt, 1, wx.EXPAND|wx.ALL, 6) 21 | sizer.Add(save_button, 0, wx.EXPAND|wx.ALL, 6) 22 | 23 | self.SetSizer(sizer) 24 | self.Show() 25 | 26 | def on_save(self, event): 27 | out = BytesIO() 28 | handler = wx.richtext.RichTextXMLHandler() 29 | rt_buffer = self.rt.GetBuffer() 30 | handler.SaveFile(rt_buffer, out) 31 | self.xml_content = out.getvalue() 32 | print(self.xml_content) 33 | 34 | 35 | if __name__ == "__main__": 36 | app = wx.App(False) 37 | frame = MyFrame() 38 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_25_fade_in/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class Fader(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title='Fader Example') 7 | self.amount = 5 8 | self.delta = 5 9 | panel = wx.Panel(self, wx.ID_ANY) 10 | 11 | self.SetTransparent(self.amount) 12 | 13 | # Fader Timer 14 | self.timer = wx.Timer(self, wx.ID_ANY) 15 | self.timer.Start(60) 16 | self.Bind(wx.EVT_TIMER, self.AlphaCycle) 17 | 18 | def AlphaCycle(self, evt): 19 | """ 20 | Fade the frame in and out 21 | """ 22 | self.amount += self.delta 23 | if self.amount >= 255: 24 | self.delta = -self.delta 25 | self.amount = 255 26 | if self.amount <= 0: 27 | self.amount = 0 28 | self.delta = 5 29 | self.SetTransparent(self.amount) 30 | 31 | if __name__ == '__main__': 32 | app = wx.App(False) 33 | frm = Fader() 34 | frm.Show() 35 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_26_flashing_text/changing_text.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import wx 4 | 5 | 6 | class MyPanel(wx.Panel): 7 | """""" 8 | 9 | def __init__(self, parent): 10 | """Constructor""" 11 | wx.Panel.__init__(self, parent) 12 | 13 | self.font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL) 14 | self.flashingText = wx.StaticText(self, label="I flash a LOT!") 15 | self.flashingText.SetFont(self.font) 16 | 17 | self.timer = wx.Timer(self) 18 | self.Bind(wx.EVT_TIMER, self.update, self.timer) 19 | self.timer.Start(1000) 20 | 21 | def update(self, event): 22 | """""" 23 | now = int(time.time()) 24 | mod = now % 2 25 | print (now) 26 | print (mod) 27 | if mod: 28 | self.flashingText.SetLabel("Current time: %i" % now) 29 | else: 30 | self.flashingText.SetLabel("Oops! It's mod zero time!") 31 | colors = ["blue", "green", "red", "yellow"] 32 | self.flashingText.SetForegroundColour(random.choice(colors)) 33 | 34 | 35 | class MyFrame(wx.Frame): 36 | """""" 37 | 38 | def __init__(self): 39 | """Constructor""" 40 | wx.Frame.__init__(self, None, title="Flashing text!") 41 | panel = MyPanel(self) 42 | self.Show() 43 | 44 | 45 | if __name__ == "__main__": 46 | app = wx.App(False) 47 | frame = MyFrame() 48 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_26_flashing_text/flashing_text.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import wx 4 | 5 | 6 | class MyPanel(wx.Panel): 7 | """""" 8 | 9 | def __init__(self, parent): 10 | """Constructor""" 11 | wx.Panel.__init__(self, parent) 12 | 13 | self.font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL) 14 | self.label = "I flash a LOT!" 15 | self.flashingText = wx.StaticText(self, label=self.label) 16 | self.flashingText.SetFont(self.font) 17 | 18 | self.timer = wx.Timer(self) 19 | self.Bind(wx.EVT_TIMER, self.update, self.timer) 20 | self.timer.Start(1000) 21 | 22 | def update(self, event): 23 | """""" 24 | colors = ["blue", "green", "red", "yellow"] 25 | self.flashingText.SetLabel(self.label) 26 | self.flashingText.SetForegroundColour(random.choice(colors)) 27 | 28 | 29 | class MyFrame(wx.Frame): 30 | """""" 31 | 32 | def __init__(self): 33 | """Constructor""" 34 | wx.Frame.__init__(self, None, title="Flashing text!") 35 | panel = MyPanel(self) 36 | self.Show() 37 | 38 | 39 | if __name__ == "__main__": 40 | app = wx.App(False) 41 | frame = MyFrame() 42 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_27_maximizing_frame/fullscreen.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyPanel(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """Constructor""" 9 | wx.Panel.__init__(self, parent) 10 | 11 | self.Bind(wx.EVT_KEY_DOWN, self.onKey) 12 | 13 | def onKey(self, event): 14 | """ 15 | Check for ESC key press and exit is ESC is pressed 16 | """ 17 | key_code = event.GetKeyCode() 18 | if key_code == wx.WXK_ESCAPE: 19 | self.GetParent().Close() 20 | else: 21 | event.Skip() 22 | 23 | 24 | class MyFrame(wx.Frame): 25 | """""" 26 | 27 | def __init__(self): 28 | """Constructor""" 29 | wx.Frame.__init__(self, None, title="Test FullScreen") 30 | panel = MyPanel(self) 31 | self.ShowFullScreen(True) 32 | 33 | 34 | if __name__ == "__main__": 35 | app = wx.App(False) 36 | frame = MyFrame() 37 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_27_maximizing_frame/maximize.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyPanel(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """""" 9 | wx.Panel.__init__(self, parent) 10 | 11 | 12 | class MyFrame(wx.Frame): 13 | """""" 14 | 15 | def __init__(self): 16 | """""" 17 | wx.Frame.__init__(self, None, title="Test Maximize") 18 | panel = MyPanel(self) 19 | self.Show() 20 | self.Maximize(True) 21 | 22 | 23 | if __name__ == "__main__": 24 | app = wx.App(False) 25 | frame = MyFrame() 26 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/default_frame.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class DefaultFrame(wx.Frame): 5 | """ 6 | The default frame 7 | """ 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | wx.Frame.__init__(self, None, title="Default Frame") 12 | panel = wx.Panel(self) 13 | self.Show() 14 | 15 | 16 | if __name__ == "__main__": 17 | app = wx.App(False) 18 | frame = DefaultFrame() 19 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/default_frame_2.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class DefaultFrame(wx.Frame): 5 | """ 6 | The default frame 7 | """ 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | wx.Frame.__init__(self, None, title="Default Frame", 12 | style=wx.DEFAULT_FRAME_STYLE) 13 | panel = wx.Panel(self) 14 | self.Show() 15 | 16 | 17 | if __name__ == "__main__": 18 | app = wx.App(False) 19 | frame = DefaultFrame() 20 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/default_frame_3.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class DefaultFrame(wx.Frame): 5 | """ 6 | The default frame 7 | """ 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | default = (wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER 12 | | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX 13 | | wx.CLIP_CHILDREN) 14 | wx.Frame.__init__(self, None, title="Default Frame", style=default) 15 | panel = wx.Panel(self) 16 | self.Show() 17 | 18 | 19 | if __name__ == "__main__": 20 | app = wx.App(False) 21 | frame = DefaultFrame() 22 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/disabled_close_btn.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class NoCloseFrame(wx.Frame): 5 | """ 6 | This frame has no close box and the close menu is disabled 7 | """ 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | no_close = (wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER 12 | | wx.SYSTEM_MENU | wx.CAPTION | wx.CLIP_CHILDREN) 13 | wx.Frame.__init__(self, None, title="No Close", style=no_close) 14 | panel = wx.Panel(self) 15 | self.Show() 16 | 17 | 18 | if __name__ == "__main__": 19 | app = wx.App(False) 20 | frame = NoCloseFrame() 21 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/no_caption.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class NoCaptionFrame(wx.Frame): 5 | """""" 6 | 7 | def __init__(self): 8 | """Constructor""" 9 | no_caption = (wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER 10 | | wx.SYSTEM_MENU | wx.CLOSE_BOX | wx.CLIP_CHILDREN) 11 | wx.Frame.__init__(self, None, title="No Caption", style=no_caption) 12 | panel = wx.Panel(self) 13 | self.Show() 14 | 15 | 16 | if __name__ == "__main__": 17 | app = wx.App(False) 18 | frame = NoCaptionFrame() 19 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/no_max_min.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class NoMaxMinFrame(wx.Frame): 5 | """ 6 | This frame does not have maximize or minimize buttons 7 | """ 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | no_caption = (wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION 12 | | wx.CLOSE_BOX | wx.CLIP_CHILDREN 13 | | wx.FRAME_NO_TASKBAR) 14 | wx.Frame.__init__(self, None, title="No Max/Min", style=no_caption) 15 | panel = wx.Panel(self) 16 | self.Show() 17 | 18 | 19 | if __name__ == "__main__": 20 | app = wx.App(False) 21 | frame = NoMaxMinFrame() 22 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/no_resize.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class NoResizeFrame(wx.Frame): 5 | """ 6 | This frame cannot be resized. It can only be minimized 7 | and closed 8 | """ 9 | 10 | def __init__(self): 11 | """Constructor""" 12 | no_resize = wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER | 13 | wx.MAXIMIZE_BOX) 14 | wx.Frame.__init__(self, None, title="No Resize", style=no_resize) 15 | panel = wx.Panel(self) 16 | self.Show() 17 | 18 | 19 | if __name__ == "__main__": 20 | app = wx.App(False) 21 | frame = NoResizeFrame() 22 | app.MainLoop() 23 | -------------------------------------------------------------------------------- /recipe_28_frame_styles/no_system_menu.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class NoSystemMenuFrame(wx.Frame): 5 | """ 6 | There is no system menu, which means the title bar is there, but 7 | no buttons and no menu when clicking the top left hand corner 8 | of the frame 9 | """ 10 | 11 | def __init__(self): 12 | """Constructor""" 13 | no_sys_menu = wx.CAPTION 14 | wx.Frame.__init__(self, None, title="No System Menu", 15 | style=no_sys_menu) 16 | panel = wx.Panel(self) 17 | self.Show() 18 | 19 | 20 | if __name__ == "__main__": 21 | app = wx.App(False) 22 | frame = NoSystemMenuFrame() 23 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_28_frame_styles/stay_on_top.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class StayOnTopFrame(wx.Frame): 5 | """ 6 | A frame that stays on top of all the others 7 | """ 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | on_top = wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP 12 | wx.Frame.__init__(self, None, title="Stay on top", style=on_top) 13 | panel = wx.Panel(self) 14 | self.Show() 15 | 16 | 17 | if __name__ == "__main__": 18 | app = wx.App(False) 19 | frame = StayOnTopFrame() 20 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_29_taskbar_icons/main_classic.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class PythonIcon(wx.TaskBarIcon): 5 | TBMENU_RESTORE = wx.NewId() 6 | TBMENU_CLOSE = wx.NewId() 7 | TBMENU_CHANGE = wx.NewId() 8 | TBMENU_REMOVE = wx.NewId() 9 | 10 | def __init__(self, frame): 11 | wx.TaskBarIcon.__init__(self) 12 | self.frame = frame 13 | 14 | # Set the image 15 | icon = wx.Icon('python.ico', wx.BITMAP_TYPE_ICO) 16 | 17 | self.SetIcon(icon, "Python") 18 | 19 | # bind some events 20 | self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE) 21 | self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.OnTaskBarLeftClick) 22 | 23 | def CreatePopupMenu(self, evt=None): 24 | """ 25 | This method is called by the base class when it needs to popup 26 | the menu for the default EVT_RIGHT_DOWN event. Just create 27 | the menu how you want it and return it from this function, 28 | the base class takes care of the rest. 29 | """ 30 | menu = wx.Menu() 31 | menu.Append(self.TBMENU_RESTORE, "Open Program") 32 | menu.Append(self.TBMENU_CHANGE, "Show all the Items") 33 | menu.AppendSeparator() 34 | menu.Append(self.TBMENU_CLOSE, "Exit Program") 35 | return menu 36 | 37 | def OnTaskBarActivate(self, evt): 38 | """""" 39 | pass 40 | 41 | def OnTaskBarClose(self, evt): 42 | """ 43 | Destroy the taskbar icon and frame from the taskbar icon itself 44 | """ 45 | self.frame.Close() 46 | 47 | def OnTaskBarLeftClick(self, evt): 48 | """ 49 | Create the right-click menu 50 | """ 51 | menu = self.CreatePopupMenu() 52 | self.PopupMenu(menu) 53 | menu.Destroy() 54 | 55 | 56 | class MyForm(wx.Frame): 57 | 58 | def __init__(self): 59 | wx.Frame.__init__(self, None, title="TaskBarIcon Tutorial", 60 | size=(500,500)) 61 | panel = wx.Panel(self) 62 | self.tbIcon = PythonIcon(self) 63 | self.Bind(wx.EVT_CLOSE, self.onClose) 64 | 65 | def onClose(self, evt): 66 | """ 67 | Destroy the taskbar icon and the frame 68 | """ 69 | self.tbIcon.RemoveIcon() 70 | self.tbIcon.Destroy() 71 | self.Destroy() 72 | 73 | 74 | if __name__ == "__main__": 75 | app = wx.App(False) 76 | frame = MyForm().Show() 77 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_29_taskbar_icons/main_phoenix.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.adv 3 | 4 | class PythonIcon(wx.adv.TaskBarIcon): 5 | TBMENU_RESTORE = wx.NewId() 6 | TBMENU_CLOSE = wx.NewId() 7 | TBMENU_CHANGE = wx.NewId() 8 | TBMENU_REMOVE = wx.NewId() 9 | 10 | def __init__(self, frame): 11 | wx.adv.TaskBarIcon.__init__(self) 12 | self.frame = frame 13 | 14 | # Set the image 15 | icon = wx.Icon('python.ico', wx.BITMAP_TYPE_ICO) 16 | 17 | self.SetIcon(icon, "Python") 18 | 19 | # bind some events 20 | self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE) 21 | self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.OnTaskBarLeftClick) 22 | 23 | def CreatePopupMenu(self, evt=None): 24 | """ 25 | This method is called by the base class when it needs to popup 26 | the menu for the default EVT_RIGHT_DOWN event. Just create 27 | the menu how you want it and return it from this function, 28 | the base class takes care of the rest. 29 | """ 30 | menu = wx.Menu() 31 | menu.Append(self.TBMENU_RESTORE, "Open Program") 32 | menu.Append(self.TBMENU_CHANGE, "Show all the Items") 33 | menu.AppendSeparator() 34 | menu.Append(self.TBMENU_CLOSE, "Exit Program") 35 | return menu 36 | 37 | def OnTaskBarActivate(self, evt): 38 | """""" 39 | pass 40 | 41 | def OnTaskBarClose(self, evt): 42 | """ 43 | Destroy the taskbar icon and frame from the taskbar icon itself 44 | """ 45 | self.frame.Close() 46 | 47 | def OnTaskBarLeftClick(self, evt): 48 | """ 49 | Create the right-click menu 50 | """ 51 | menu = self.CreatePopupMenu() 52 | self.PopupMenu(menu) 53 | menu.Destroy() 54 | 55 | 56 | class MyForm(wx.Frame): 57 | 58 | def __init__(self): 59 | wx.Frame.__init__(self, None, title="TaskBarIcon Tutorial", 60 | size=(500,500)) 61 | panel = wx.Panel(self) 62 | self.tbIcon = PythonIcon(self) 63 | self.Bind(wx.EVT_CLOSE, self.onClose) 64 | 65 | def onClose(self, evt): 66 | """ 67 | Destroy the taskbar icon and the frame 68 | """ 69 | self.tbIcon.RemoveIcon() 70 | self.tbIcon.Destroy() 71 | self.Destroy() 72 | 73 | 74 | if __name__ == "__main__": 75 | app = wx.App(False) 76 | frame = MyForm().Show() 77 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_29_taskbar_icons/python.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_29_taskbar_icons/python.ico -------------------------------------------------------------------------------- /recipe_2_screenshots/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import wx 3 | import snapshotPrinter 4 | 5 | class MyForm(wx.Frame): 6 | 7 | def __init__(self): 8 | wx.Frame.__init__(self, None, title="Screenshot Tutorial") 9 | 10 | panel = wx.Panel(self) 11 | screenshotBtn = wx.Button(panel, label="Take Screenshot") 12 | screenshotBtn.Bind(wx.EVT_BUTTON, self.onTakeScreenShot) 13 | printBtn = wx.Button(panel, label="Print Screenshot") 14 | printBtn.Bind(wx.EVT_BUTTON, self.onPrint) 15 | 16 | sizer = wx.BoxSizer(wx.HORIZONTAL) 17 | sizer.Add(screenshotBtn, 0, wx.ALL|wx.CENTER, 5) 18 | sizer.Add(printBtn, 0, wx.ALL|wx.CENTER, 5) 19 | panel.SetSizer(sizer) 20 | 21 | def onTakeScreenShot(self, event): 22 | """ 23 | Takes a screenshot of the screen at give pos & size (rect). 24 | 25 | Method based on a script by Andrea Gavana 26 | """ 27 | print('Taking screenshot...') 28 | rect = self.GetRect() 29 | 30 | # adjust widths for Linux (figured out by John Torres 31 | # http://article.gmane.org/gmane.comp.python.wxpython/67327) 32 | if sys.platform == 'linux2': 33 | client_x, client_y = self.ClientToScreen((0, 0)) 34 | border_width = client_x - rect.x 35 | title_bar_height = client_y - rect.y 36 | rect.width += (border_width * 2) 37 | rect.height += title_bar_height + border_width 38 | 39 | # Create a DC for the whole screen area 40 | dcScreen = wx.ScreenDC() 41 | 42 | # Create a Bitmap that will hold the screenshot image later on 43 | # Note that the Bitmap must have a size big enough to hold the screenshot 44 | # -1 means using the current default colour depth 45 | bmp = wx.EmptyBitmap(rect.width, rect.height) 46 | 47 | #Create a memory DC that will be used for actually taking the screenshot 48 | memDC = wx.MemoryDC() 49 | 50 | # Tell the memory DC to use our Bitmap 51 | # all drawing action on the memory DC will go to the Bitmap now 52 | memDC.SelectObject(bmp) 53 | 54 | # Blit (in this case copy) the actual screen on the memory DC 55 | # and thus the Bitmap 56 | memDC.Blit( 0, # Copy to this X coordinate 57 | 0, # Copy to this Y coordinate 58 | rect.width, # Copy this width 59 | rect.height, # Copy this height 60 | dcScreen, # Where to copy from 61 | rect.x, # What's the X offset in the original DC? 62 | rect.y # What's the Y offset in the original DC? 63 | ) 64 | 65 | # Select the Bitmap out of the memory DC by selecting a new 66 | # uninitialized Bitmap 67 | memDC.SelectObject(wx.NullBitmap) 68 | 69 | img = bmp.ConvertToImage() 70 | fileName = "myImage.png" 71 | img.SaveFile(fileName, wx.BITMAP_TYPE_PNG) 72 | print('...saving as png!') 73 | 74 | def onPrint(self, event): 75 | """ 76 | Send screenshot to the printer 77 | """ 78 | printer = snapshotPrinter.SnapshotPrinter() 79 | printer.sendToPrinter() 80 | 81 | # Run the program 82 | if __name__ == "__main__": 83 | app = wx.App(False) 84 | frame = MyForm() 85 | frame.Show() 86 | app.MainLoop() 87 | -------------------------------------------------------------------------------- /recipe_2_screenshots/myImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_2_screenshots/myImage.png -------------------------------------------------------------------------------- /recipe_2_screenshots/screenshot.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /recipe_2_screenshots/snapshotPrinter.py: -------------------------------------------------------------------------------- 1 | # snapshotPrinter.py 2 | 3 | import os 4 | import wx 5 | from wx.html import HtmlEasyPrinting, HtmlWindow 6 | 7 | class SnapshotPrinter(wx.Frame): 8 | 9 | def __init__(self, title='Snapshot Printer'): 10 | wx.Frame.__init__(self, None, title=title, 11 | size=(650,400)) 12 | 13 | self.panel = wx.Panel(self) 14 | self.printer = HtmlEasyPrinting( 15 | name='Printing', parentWindow=None) 16 | 17 | self.html = HtmlWindow(self.panel) 18 | self.html.SetRelatedFrame(self, self.GetTitle()) 19 | 20 | if not os.path.exists('screenshot.htm'): 21 | self.createHtml() 22 | self.html.LoadPage('screenshot.htm') 23 | 24 | pageSetupBtn = wx.Button(self.panel, label='Page Setup') 25 | printBtn = wx.Button(self.panel, label='Print') 26 | cancelBtn = wx.Button(self.panel, label='Cancel') 27 | 28 | self.Bind(wx.EVT_BUTTON, self.onSetup, pageSetupBtn) 29 | self.Bind(wx.EVT_BUTTON, self.onPrint, printBtn) 30 | self.Bind(wx.EVT_BUTTON, self.onCancel, cancelBtn) 31 | 32 | sizer = wx.BoxSizer(wx.VERTICAL) 33 | btnSizer = wx.BoxSizer(wx.HORIZONTAL) 34 | 35 | sizer.Add(self.html, 1, wx.GROW) 36 | btnSizer.Add(pageSetupBtn, 0, wx.ALL, 5) 37 | btnSizer.Add(printBtn, 0, wx.ALL, 5) 38 | btnSizer.Add(cancelBtn, 0, wx.ALL, 5) 39 | sizer.Add(btnSizer) 40 | 41 | self.panel.SetSizer(sizer) 42 | self.panel.SetAutoLayout(True) 43 | 44 | def createHtml(self): 45 | ''' 46 | Creates an html file in the home directory of the application 47 | that contains the information to display the snapshot 48 | ''' 49 | print('creating html...') 50 | 51 | html = '''\n\n
52 | 53 |
\n\n''' 54 | with open('screenshot.htm', 'w') as fobj: 55 | fobj.write(html) 56 | 57 | def onSetup(self, event): 58 | self.printer.PageSetup() 59 | 60 | def onPrint(self, event): 61 | self.sendToPrinter() 62 | 63 | def sendToPrinter(self): 64 | self.printer.GetPrintData().SetPaperId(wx.PAPER_LETTER) 65 | self.printer.PrintFile(self.html.GetOpenedPage()) 66 | 67 | def onCancel(self, event): 68 | self.Close() 69 | 70 | 71 | if __name__ == '__main__': 72 | app = wx.App(False) 73 | frame = SnapshotPrinter() 74 | frame.Show() 75 | app.MainLoop() 76 | -------------------------------------------------------------------------------- /recipe_30_minimize_to_tray/custTray.py: -------------------------------------------------------------------------------- 1 | # custTray.py 2 | 3 | import wx 4 | 5 | 6 | class CustomTaskBarIcon(wx.TaskBarIcon): 7 | """""" 8 | 9 | def __init__(self, frame): 10 | """Constructor""" 11 | wx.TaskBarIcon.__init__(self) 12 | self.frame = frame 13 | 14 | icon = wx.Icon('python.ico', wx.BITMAP_TYPE_ICO) 15 | 16 | self.SetIcon(icon, "Restore") 17 | 18 | self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.OnTaskBarLeftClick) 19 | 20 | def OnTaskBarActivate(self, evt): 21 | """""" 22 | pass 23 | 24 | def OnTaskBarClose(self, evt): 25 | """ 26 | Destroy the taskbar icon and frame from the taskbar icon itself 27 | """ 28 | self.frame.Close() 29 | 30 | def OnTaskBarLeftClick(self, evt): 31 | """ 32 | Create the right-click menu 33 | """ 34 | self.frame.Show() 35 | self.frame.Restore() -------------------------------------------------------------------------------- /recipe_30_minimize_to_tray/custTray_phoenix.py: -------------------------------------------------------------------------------- 1 | # custTray_phoenix.py 2 | 3 | import wx 4 | import wx.adv 5 | 6 | 7 | class CustomTaskBarIcon(wx.adv.TaskBarIcon): 8 | """""" 9 | 10 | def __init__(self, frame): 11 | """Constructor""" 12 | wx.adv.TaskBarIcon.__init__(self) 13 | self.frame = frame 14 | 15 | icon = wx.Icon('python.ico', wx.BITMAP_TYPE_ICO) 16 | 17 | self.SetIcon(icon, "Restore") 18 | 19 | self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.OnTaskBarLeftClick) 20 | 21 | def OnTaskBarActivate(self, evt): 22 | """""" 23 | pass 24 | 25 | def OnTaskBarClose(self, evt): 26 | """ 27 | Destroy the taskbar icon and frame from the taskbar icon itself 28 | """ 29 | self.frame.Close() 30 | 31 | def OnTaskBarLeftClick(self, evt): 32 | """ 33 | Create the right-click menu 34 | """ 35 | self.frame.Show() 36 | self.frame.Restore() -------------------------------------------------------------------------------- /recipe_30_minimize_to_tray/main_classic.py: -------------------------------------------------------------------------------- 1 | import custTray 2 | import wx 3 | 4 | 5 | class MainFrame(wx.Frame): 6 | """""" 7 | 8 | def __init__(self): 9 | """Constructor""" 10 | wx.Frame.__init__(self, None, title="Minimize to Tray") 11 | panel = wx.Panel(self) 12 | self.tbIcon = custTray.CustomTaskBarIcon(self) 13 | 14 | self.Bind(wx.EVT_ICONIZE, self.onMinimize) 15 | self.Bind(wx.EVT_CLOSE, self.onClose) 16 | 17 | self.Show() 18 | 19 | def onClose(self, evt): 20 | """ 21 | Destroy the taskbar icon and the frame 22 | """ 23 | self.tbIcon.RemoveIcon() 24 | self.tbIcon.Destroy() 25 | self.Destroy() 26 | 27 | def onMinimize(self, event): 28 | """ 29 | When minimizing, hide the frame so it "minimizes to tray" 30 | """ 31 | if self.IsIconized(): 32 | self.Hide() 33 | 34 | 35 | def main(): 36 | """""" 37 | app = wx.App(False) 38 | frame = MainFrame() 39 | app.MainLoop() 40 | 41 | if __name__ == "__main__": 42 | main() -------------------------------------------------------------------------------- /recipe_30_minimize_to_tray/main_phoenix.py: -------------------------------------------------------------------------------- 1 | import custTray_phoenix as custTray 2 | import wx 3 | 4 | 5 | class MainFrame(wx.Frame): 6 | """""" 7 | 8 | def __init__(self): 9 | """Constructor""" 10 | wx.Frame.__init__(self, None, title="Minimize to Tray") 11 | panel = wx.Panel(self) 12 | self.tbIcon = custTray.CustomTaskBarIcon(self) 13 | 14 | self.Bind(wx.EVT_ICONIZE, self.onMinimize) 15 | self.Bind(wx.EVT_CLOSE, self.onClose) 16 | 17 | self.Show() 18 | 19 | def onClose(self, evt): 20 | """ 21 | Destroy the taskbar icon and the frame 22 | """ 23 | self.tbIcon.RemoveIcon() 24 | self.tbIcon.Destroy() 25 | self.Destroy() 26 | 27 | def onMinimize(self, event): 28 | """ 29 | When minimizing, hide the frame so it "minimizes to tray" 30 | """ 31 | if self.IsIconized(): 32 | self.Hide() 33 | 34 | 35 | def main(): 36 | """""" 37 | app = wx.App(False) 38 | frame = MainFrame() 39 | app.MainLoop() 40 | 41 | if __name__ == "__main__": 42 | main() -------------------------------------------------------------------------------- /recipe_30_minimize_to_tray/python.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_30_minimize_to_tray/python.ico -------------------------------------------------------------------------------- /recipe_31_children_from_sizers/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyApp(wx.Frame): 5 | """""" 6 | 7 | def __init__(self): 8 | """Constructor""" 9 | title = 'Get Children from Sizer' 10 | wx.Frame.__init__(self, None, title=title) 11 | panel = wx.Panel(self) 12 | 13 | lbl = wx.StaticText(panel, label="I'm a label!") 14 | txt = wx.TextCtrl(panel, value="blah blah") 15 | btn = wx.Button(panel, label="Clear") 16 | btn.Bind(wx.EVT_BUTTON, self.onClear) 17 | 18 | self.sizer = wx.BoxSizer(wx.VERTICAL) 19 | self.sizer.Add(lbl, 0, wx.ALL, 5) 20 | self.sizer.Add(txt, 0, wx.ALL, 5) 21 | self.sizer.Add(btn, 0, wx.ALL, 5) 22 | 23 | panel.SetSizer(self.sizer) 24 | 25 | def onClear(self, event): 26 | """ 27 | Button event handler for clearing TextCtrl widgets 28 | """ 29 | children = self.sizer.GetChildren() 30 | 31 | for child in children: 32 | widget = child.GetWindow() 33 | print widget 34 | if isinstance(widget, wx.TextCtrl): 35 | widget.Clear() 36 | 37 | 38 | if __name__ == "__main__": 39 | app = wx.App(False) 40 | frame = MyApp() 41 | frame.Show() 42 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_32_clipboard/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class ClipboardPanel(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """Constructor""" 9 | wx.Panel.__init__(self, parent) 10 | 11 | lbl = wx.StaticText(self, label="Enter text to copy to clipboard:") 12 | self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE) 13 | copyBtn = wx.Button(self, label="Copy") 14 | copyBtn.Bind(wx.EVT_BUTTON, self.onCopy) 15 | copyFlushBtn = wx.Button(self, label="Copy and Flush") 16 | copyFlushBtn.Bind(wx.EVT_BUTTON, self.onCopyAndFlush) 17 | 18 | sizer = wx.BoxSizer(wx.VERTICAL) 19 | sizer.Add(lbl, 0, wx.ALL, 5) 20 | sizer.Add(self.text, 1, wx.EXPAND) 21 | sizer.Add(copyBtn, 0, wx.ALL|wx.CENTER, 5) 22 | sizer.Add(copyFlushBtn, 0, wx.ALL|wx.CENTER, 5) 23 | self.SetSizer(sizer) 24 | 25 | def onCopy(self, event): 26 | """""" 27 | self.dataObj = wx.TextDataObject() 28 | self.dataObj.SetText(self.text.GetValue()) 29 | if wx.TheClipboard.Open(): 30 | wx.TheClipboard.SetData(self.dataObj) 31 | wx.TheClipboard.Close() 32 | else: 33 | wx.MessageBox("Unable to open the clipboard", "Error") 34 | 35 | def onCopyAndFlush(self, event): 36 | """ 37 | Copy to the clipboard and close the application 38 | """ 39 | self.dataObj = wx.TextDataObject() 40 | self.dataObj.SetText(self.text.GetValue()) 41 | if wx.TheClipboard.Open(): 42 | wx.TheClipboard.SetData(self.dataObj) 43 | wx.TheClipboard.Flush() 44 | else: 45 | wx.MessageBox("Unable to open the clipboard", "Error") 46 | 47 | self.GetParent().Close() 48 | 49 | 50 | class ClipboardFrame(wx.Frame): 51 | """""" 52 | 53 | def __init__(self): 54 | """Constructor""" 55 | wx.Frame.__init__(self, None, title="Clipboard Tutorial") 56 | panel = ClipboardPanel(self) 57 | self.Show() 58 | 59 | 60 | if __name__ == "__main__": 61 | app = wx.App(False) 62 | frame = ClipboardFrame() 63 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_33_focus/acquire_focus.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title="Focus Tutorial 1") 7 | 8 | 9 | panel = wx.Panel(self) 10 | panel.Bind(wx.EVT_SET_FOCUS, self.onFocus) 11 | 12 | def onFocus(self, event): 13 | print("panel received focus!") 14 | 15 | # Run the program 16 | if __name__ == "__main__": 17 | app = wx.App(False) 18 | frame = MyForm().Show() 19 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_33_focus/acquire_focus_2.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title="Focus Tutorial 1a") 7 | 8 | panel = wx.Panel(self) 9 | panel.Bind(wx.EVT_SET_FOCUS, self.onFocus) 10 | txt = wx.TextCtrl(panel, wx.ID_ANY, "") 11 | 12 | def onFocus(self, event): 13 | print("panel received focus!") 14 | 15 | 16 | if __name__ == "__main__": 17 | app = wx.App(False) 18 | frame = MyForm().Show() 19 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_33_focus/focus_finder.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title="Focus Finder") 7 | 8 | panel = wx.Panel(self, wx.ID_ANY) 9 | panel.Bind(wx.EVT_SET_FOCUS, self.onFocus) 10 | txt = wx.StaticText( 11 | panel, label="This label cannot receive focus") 12 | 13 | self.timer = wx.Timer(self) 14 | self.Bind(wx.EVT_TIMER, self.onTimer) 15 | self.timer.Start(1000) 16 | 17 | def onFocus(self, event): 18 | print("panel received focus!") 19 | 20 | def onTimer(self, evt): 21 | print('Focused window:', wx.Window.FindFocus()) 22 | 23 | 24 | if __name__ == "__main__": 25 | app = wx.App(False) 26 | frame = MyForm().Show() 27 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_33_focus/losing_focus.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title="Losing Focus") 7 | 8 | # Add a panel so it looks the correct on all platforms 9 | panel = wx.Panel(self, wx.ID_ANY) 10 | 11 | txt = wx.TextCtrl(panel, value="") 12 | txt.Bind(wx.EVT_SET_FOCUS, self.onFocus) 13 | txt.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) 14 | btn = wx.Button(panel, wx.ID_ANY, "Test") 15 | 16 | sizer = wx.BoxSizer(wx.VERTICAL) 17 | sizer.Add(txt, 0, wx.ALL, 5) 18 | sizer.Add(btn, 0, wx.ALL, 5) 19 | panel.SetSizer(sizer) 20 | 21 | def onFocus(self, event): 22 | print("widget received focus!") 23 | 24 | def onKillFocus(self, event): 25 | print("widget lost focus!") 26 | 27 | 28 | if __name__ == "__main__": 29 | app = wx.App(False) 30 | frame = MyForm().Show() 31 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_34_url_shortening/ars_example.py: -------------------------------------------------------------------------------- 1 | import re 2 | import urllib 3 | import urllib2 4 | import wx 5 | 6 | class ArsShortener(wx.Frame): 7 | 8 | def __init__(self): 9 | wx.Frame.__init__(self, None, wx.ID_ANY, 10 | 'wxArsShortener', size=(300,70)) 11 | 12 | # Add a panel so it looks the correct on all platforms 13 | panel = wx.Panel(self, wx.ID_ANY) 14 | 15 | self.txt = wx.TextCtrl(panel, wx.ID_ANY, "", size=(300, -1)) 16 | self.txt.Bind(wx.EVT_TEXT, self.onTextChange) 17 | 18 | sizer = wx.BoxSizer(wx.VERTICAL) 19 | sizer.Add(self.txt, 0, wx.EXPAND, 5) 20 | panel.SetSizer(sizer) 21 | 22 | def onTextChange(self, event): 23 | """""" 24 | text = self.txt.GetValue() 25 | textLength = len(text) 26 | if re.match("^https?://[^ ]+", text) and textLength > 20: 27 | apiURL = "http://is.gd/api.php?" + urllib.urlencode(dict(longURL=text)) 28 | shortened_URL = urllib2.urlopen(apiURL).read() 29 | self.txt.SetValue(shortened_URL) 30 | 31 | if __name__ == '__main__': 32 | app = wx.App(False) 33 | frame = ArsShortener() 34 | frame.Show() 35 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_34_url_shortening/ars_example_py3.py: -------------------------------------------------------------------------------- 1 | # Python 3 2 | 3 | import re 4 | import urllib.parse 5 | import urllib.request 6 | import wx 7 | 8 | class ArsShortener(wx.Frame): 9 | 10 | def __init__(self): 11 | wx.Frame.__init__(self, None, wx.ID_ANY, 12 | 'wxArsShortener', size=(300,70)) 13 | 14 | # Add a panel so it looks the correct on all platforms 15 | panel = wx.Panel(self, wx.ID_ANY) 16 | 17 | self.txt = wx.TextCtrl(panel, wx.ID_ANY, "", size=(300, -1)) 18 | self.txt.Bind(wx.EVT_TEXT, self.onTextChange) 19 | 20 | sizer = wx.BoxSizer(wx.VERTICAL) 21 | sizer.Add(self.txt, 0, wx.EXPAND, 5) 22 | panel.SetSizer(sizer) 23 | 24 | def onTextChange(self, event): 25 | """""" 26 | text = self.txt.GetValue() 27 | textLength = len(text) 28 | if re.match("^https?://[^ ]+", text) and textLength > 20: 29 | apiURL = "http://is.gd/api.php?" + urllib.parse.urlencode(dict(longURL=text)) 30 | 31 | shortened_URL = urllib.request.urlopen(apiURL).read() 32 | self.txt.SetValue(shortened_URL) 33 | 34 | if __name__ == '__main__': 35 | app = wx.App(False) 36 | frame = ArsShortener() 37 | frame.Show() 38 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_34_url_shortening/shortening_py2.py: -------------------------------------------------------------------------------- 1 | import re 2 | import urllib 3 | import urllib2 4 | import wx 5 | 6 | bitlyFlag = True 7 | tinyURLFlag = True 8 | 9 | try: 10 | import bitly 11 | except ImportError: 12 | bitlyFlag = False 13 | 14 | try: 15 | import tinyurl 16 | except ImportError: 17 | tinyURLFlag = False 18 | 19 | 20 | class MainPanel(wx.Panel): 21 | """ 22 | """ 23 | 24 | def __init__(self, parent): 25 | """Constructor""" 26 | wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) 27 | self.frame = parent 28 | 29 | # create the widgets 30 | self.createLayout() 31 | 32 | def createLayout(self): 33 | """ 34 | Create widgets and lay them out 35 | """ 36 | choices = ["is.gd"] 37 | if bitlyFlag: 38 | choices.append("bit.ly") 39 | if tinyURLFlag: 40 | choices.append("tinyURL") 41 | choices.sort() 42 | 43 | # create the widgets 44 | self.URLCbo = wx.ComboBox(self, wx.ID_ANY, "is.gd", 45 | choices=choices, 46 | size=wx.DefaultSize, 47 | style=wx.CB_DROPDOWN) 48 | self.inputURLTxt = wx.TextCtrl(self, value="Paste long URL here") 49 | self.inputURLTxt.Bind(wx.EVT_SET_FOCUS, self.onFocus) 50 | self.outputURLTxt = wx.TextCtrl(self, style=wx.TE_READONLY) 51 | 52 | shortenBtn = wx.Button(self, label="Shorten URL") 53 | shortenBtn.Bind(wx.EVT_BUTTON, self.onShorten) 54 | copyBtn = wx.Button(self, label="Copy to Clipboard") 55 | copyBtn.Bind(wx.EVT_BUTTON, self.onCopy) 56 | 57 | # create the sizers 58 | mainSizer = wx.BoxSizer(wx.VERTICAL) 59 | btnSizer = wx.BoxSizer(wx.HORIZONTAL) 60 | 61 | # layout the widgets 62 | mainSizer.Add(self.URLCbo, 0, wx.ALL, 5) 63 | mainSizer.Add(self.inputURLTxt, 0, 64 | wx.ALL|wx.EXPAND, 5) 65 | mainSizer.Add(self.outputURLTxt, 0, 66 | wx.ALL|wx.EXPAND, 5) 67 | btnSizer.Add(shortenBtn, 0, wx.ALL|wx.CENTER, 5) 68 | btnSizer.Add(copyBtn, 0, wx.ALL|wx.CENTER, 5) 69 | mainSizer.Add(btnSizer, 0, wx.ALL|wx.CENTER, 5) 70 | self.SetSizer(mainSizer) 71 | 72 | def onCopy(self, event): 73 | """ 74 | Copies data to the clipboard or displays an error 75 | dialog if the clipboard is inaccessible. 76 | """ 77 | text = self.outputURLTxt.GetValue() 78 | self.do = wx.TextDataObject() 79 | self.do.SetText(text) 80 | if wx.TheClipboard.Open(): 81 | wx.TheClipboard.SetData(self.do) 82 | wx.TheClipboard.Close() 83 | status = "Copied %s to clipboard" % text 84 | self.frame.statusbar.SetStatusText(status) 85 | else: 86 | wx.MessageBox("Unable to open the clipboard", "Error") 87 | 88 | def onFocus(self, event): 89 | """ 90 | When control is given the focus, it is cleared 91 | """ 92 | self.inputURLTxt.SetValue("") 93 | 94 | def onShorten(self, event): 95 | """ 96 | Shortens a URL using the service specified. 97 | Then sets the text control to the new URL. 98 | """ 99 | text = self.inputURLTxt.GetValue() 100 | textLength = len(text) 101 | 102 | if re.match("^https?://[^ ]+", text) and textLength > 20: 103 | pass 104 | else: 105 | wx.MessageBox("URL is already tiny!", "Error") 106 | return 107 | 108 | URL = self.URLCbo.GetValue() 109 | if URL == "is.gd": 110 | self.shortenWithIsGd(text) 111 | elif URL == "bit.ly": 112 | self.shortenWithBitly(text) 113 | elif URL == "tinyurl": 114 | self.shortenWithTinyURL(text) 115 | 116 | def shortenWithBitly(self, text): 117 | """ 118 | Shortens the URL in the text control using bit.ly 119 | 120 | Requires a bit.ly account and API key 121 | """ 122 | bitly.API_LOGIN = "username" 123 | bitly.API_KEY = "api_key" 124 | URL = bitly.shorten(text) 125 | self.outputURLTxt.SetValue(URL) 126 | 127 | def shortenWithIsGd(self, text): 128 | """ 129 | Shortens the URL with is.gd using URLlib and URLlib2 130 | """ 131 | 132 | apiURL = "http://is.gd/api.php?" + urllib.urlencode(dict(longURL=text)) 133 | shortURL = urllib2.urlopen(apiURL).read() 134 | self.outputURLTxt.SetValue(shortURL) 135 | 136 | def shortenWithTinyURL(self, text): 137 | """ 138 | Shortens the URL with tinyURL 139 | """ 140 | print "in tinyurl" 141 | URL = tinyurl.create_one(text) 142 | self.outputURLTxt.SetValue(URL) 143 | 144 | 145 | class URLFrame(wx.Frame): 146 | """ 147 | wx.Frame class 148 | """ 149 | 150 | def __init__(self): 151 | """Constructor""" 152 | title = "URL Shortener" 153 | wx.Frame.__init__(self, None, wx.ID_ANY, 154 | title=title, size=(650, 220)) 155 | panel = MainPanel(self) 156 | self.statusbar = self.CreateStatusBar() 157 | self.SetMinSize((650, 220)) 158 | 159 | 160 | if __name__ == "__main__": 161 | app = wx.App(False) 162 | frame = URLFrame() 163 | frame.Show() 164 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_35_using_objectlistview/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from ObjectListView import ObjectListView, ColumnDefn 3 | 4 | 5 | class Book(object): 6 | """ 7 | Model of the Book object 8 | 9 | Contains the following attributes: 10 | 'ISBN', 'Author', 'Manufacturer', 'Title' 11 | """ 12 | 13 | def __init__(self, title, author, isbn, mfg): 14 | self.isbn = isbn 15 | self.author = author 16 | self.mfg = mfg 17 | self.title = title 18 | 19 | class MainPanel(wx.Panel): 20 | 21 | def __init__(self, parent): 22 | wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) 23 | self.products = [Book("wxPython in Action", "Robin Dunn", 24 | "1932394621", "Manning"), 25 | Book("Hello World", "Warren and Carter Sande", 26 | "1933988495", "Manning") 27 | ] 28 | 29 | self.dataOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER) 30 | self.setBooks() 31 | 32 | # Allow the cell values to be edited when double-clicked 33 | self.dataOlv.cellEditMode = ObjectListView.CELLEDIT_SINGLECLICK 34 | 35 | # create an update button 36 | updateBtn = wx.Button(self, wx.ID_ANY, "Update OLV") 37 | updateBtn.Bind(wx.EVT_BUTTON, self.updateControl) 38 | 39 | # Create some sizers 40 | mainSizer = wx.BoxSizer(wx.VERTICAL) 41 | 42 | mainSizer.Add(self.dataOlv, 1, wx.ALL|wx.EXPAND, 5) 43 | mainSizer.Add(updateBtn, 0, wx.ALL|wx.CENTER, 5) 44 | self.SetSizer(mainSizer) 45 | 46 | 47 | def updateControl(self, event): 48 | """ 49 | Update the object list view widget 50 | """ 51 | print "updating..." 52 | product_dict = [{"title":"Core Python Programming", "author":"Wesley Chun", 53 | "isbn":"0132269937", "mfg":"Prentice Hall"}, 54 | {"title":"Python Programming for the Absolute Beginner", 55 | "author":"Michael Dawson", "isbn":"1598631128", 56 | "mfg":"Course Technology"}, 57 | {"title":"Learning Python", "author":"Mark Lutz", 58 | "isbn":"0596513984", "mfg":"O'Reilly"} 59 | ] 60 | data = self.products + product_dict 61 | self.dataOlv.SetObjects(data) 62 | 63 | 64 | def setBooks(self, data=None): 65 | self.dataOlv.SetColumns([ 66 | ColumnDefn("Title", "left", 220, "title"), 67 | ColumnDefn("Author", "left", 200, "author"), 68 | ColumnDefn("ISBN", "right", 100, "isbn"), 69 | ColumnDefn("Mfg", "left", 180, "mfg") 70 | ]) 71 | 72 | self.dataOlv.SetObjects(self.products) 73 | 74 | 75 | class MainFrame(wx.Frame): 76 | 77 | def __init__(self): 78 | wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, 79 | title="ObjectListView Demo", size=(800,600)) 80 | panel = MainPanel(self) 81 | 82 | 83 | class GenApp(wx.App): 84 | 85 | def __init__(self, redirect=False, filename=None): 86 | wx.App.__init__(self, redirect, filename) 87 | 88 | 89 | def OnInit(self): 90 | # create frame here 91 | frame = MainFrame() 92 | frame.Show() 93 | return True 94 | 95 | 96 | def main(): 97 | """ 98 | Run the demo 99 | """ 100 | app = GenApp() 101 | app.MainLoop() 102 | 103 | if __name__ == "__main__": 104 | main() -------------------------------------------------------------------------------- /recipe_36_panel_destruction/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class PanelOne(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """Constructor""" 9 | wx.Panel.__init__(self, parent) 10 | 11 | msg = "This panel will self-destruct in 10 seconds" 12 | self.countdown = wx.StaticText(self, label=msg) 13 | 14 | 15 | class PanelTwo(wx.Panel): 16 | """""" 17 | 18 | def __init__(self, parent): 19 | """Constructor""" 20 | wx.Panel.__init__(self, parent) 21 | 22 | txt = wx.StaticText(self, label="Panel Two") 23 | 24 | 25 | class MainFrame(wx.Frame): 26 | """""" 27 | 28 | def __init__(self): 29 | """Constructor""" 30 | wx.Frame.__init__(self, None, title="Panel Smacker") 31 | self.panelOne = PanelOne(self) 32 | self.time2die = 10 33 | 34 | self.timer = wx.Timer(self) 35 | self.Bind(wx.EVT_TIMER, self.update, self.timer) 36 | self.timer.Start(1000) 37 | 38 | self.sizer = wx.BoxSizer(wx.VERTICAL) 39 | self.sizer.Add(self.panelOne, 1, wx.EXPAND) 40 | self.SetSizer(self.sizer) 41 | 42 | def update(self, event): 43 | """""" 44 | if self.time2die < 0: 45 | self.panelOne.Destroy() 46 | self.panelTwo = PanelTwo(self) 47 | self.sizer.Add(self.panelTwo, 1, wx.EXPAND) 48 | self.Layout() 49 | self.timer.Stop() 50 | else: 51 | msg = "This panel will self-destruct in %s seconds" % self.time2die 52 | self.panelOne.countdown.SetLabel(msg) 53 | self.time2die -= 1 54 | 55 | 56 | if __name__ == "__main__": 57 | app = wx.App(False) 58 | frame = MainFrame() 59 | frame.Show() 60 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_37_panel_switching/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.grid as gridlib 3 | 4 | 5 | class PanelOne(wx.Panel): 6 | """""" 7 | 8 | def __init__(self, parent): 9 | """Constructor""" 10 | wx.Panel.__init__(self, parent=parent) 11 | txt = wx.TextCtrl(self) 12 | 13 | 14 | class PanelTwo(wx.Panel): 15 | """""" 16 | 17 | def __init__(self, parent): 18 | """Constructor""" 19 | wx.Panel.__init__(self, parent=parent) 20 | 21 | grid = gridlib.Grid(self) 22 | grid.CreateGrid(25,12) 23 | 24 | sizer = wx.BoxSizer(wx.VERTICAL) 25 | sizer.Add(grid, 0, wx.EXPAND) 26 | self.SetSizer(sizer) 27 | 28 | 29 | class MyForm(wx.Frame): 30 | 31 | def __init__(self): 32 | wx.Frame.__init__(self, None, wx.ID_ANY, 33 | "Panel Switcher Tutorial") 34 | 35 | self.panel_one = PanelOne(self) 36 | self.panel_two = PanelTwo(self) 37 | self.panel_two.Hide() 38 | 39 | self.sizer = wx.BoxSizer(wx.VERTICAL) 40 | self.sizer.Add(self.panel_one, 1, wx.EXPAND) 41 | self.sizer.Add(self.panel_two, 1, wx.EXPAND) 42 | self.SetSizer(self.sizer) 43 | 44 | 45 | menubar = wx.MenuBar() 46 | fileMenu = wx.Menu() 47 | switch_panels_menu_item = fileMenu.Append( 48 | wx.ID_ANY, 49 | "Switch Panels", 50 | "Some text") 51 | self.Bind(wx.EVT_MENU, self.onSwitchPanels, 52 | switch_panels_menu_item) 53 | menubar.Append(fileMenu, '&File') 54 | self.SetMenuBar(menubar) 55 | 56 | def onSwitchPanels(self, event): 57 | """ 58 | Event handler called when we want to switch panels 59 | """ 60 | if self.panel_one.IsShown(): 61 | self.SetTitle("Panel Two Showing") 62 | self.panel_one.Hide() 63 | self.panel_two.Show() 64 | else: 65 | self.SetTitle("Panel One Showing") 66 | self.panel_one.Show() 67 | self.panel_two.Hide() 68 | self.Layout() 69 | 70 | 71 | # Run the program 72 | if __name__ == "__main__": 73 | app = wx.App(False) 74 | frame = MyForm() 75 | frame.Show() 76 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_38_pyplot/bar_graph.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx.lib.plot import PolyLine, PlotCanvas, PlotGraphics 3 | 4 | 5 | def drawBarGraph(): 6 | # Bar graph 7 | points1=[(1,0), (1,10)] 8 | line1 = PolyLine(points1, colour='green', legend='Feb.', width=10) 9 | points1g=[(2,0), (2,4)] 10 | line1g = PolyLine(points1g, colour='red', legend='Mar.', width=10) 11 | points1b=[(3,0), (3,6)] 12 | line1b = PolyLine(points1b, colour='blue', legend='Apr.', width=10) 13 | 14 | points2=[(4,0), (4,12)] 15 | line2 = PolyLine(points2, colour='Yellow', legend='May', width=10) 16 | points2g=[(5,0), (5,8)] 17 | line2g = PolyLine(points2g, colour='orange', legend='June', width=10) 18 | points2b=[(6,0), (6,4)] 19 | line2b = PolyLine(points2b, colour='brown', legend='July', width=10) 20 | 21 | return PlotGraphics([line1, line1g, line1b, line2, line2g, line2b], 22 | "Bar Graph - (Turn on Grid, Legend)", "Months", 23 | "Number of Students") 24 | 25 | 26 | class MyGraph(wx.Frame): 27 | 28 | 29 | def __init__(self): 30 | wx.Frame.__init__(self, None, wx.ID_ANY, 31 | 'My First Plot (to take over the world!)') 32 | 33 | # Add a panel so it looks the correct on all platforms 34 | panel = wx.Panel(self, wx.ID_ANY) 35 | 36 | # create some sizers 37 | mainSizer = wx.BoxSizer(wx.VERTICAL) 38 | checkSizer = wx.BoxSizer(wx.HORIZONTAL) 39 | 40 | # create the widgets 41 | self.canvas = PlotCanvas(panel) 42 | self.canvas.Draw(drawBarGraph()) 43 | toggleGrid = wx.CheckBox(panel, label="Show Grid") 44 | toggleGrid.Bind(wx.EVT_CHECKBOX, self.onToggleGrid) 45 | toggleLegend = wx.CheckBox(panel, label="Show Legend") 46 | toggleLegend.Bind(wx.EVT_CHECKBOX, self.onToggleLegend) 47 | 48 | # layout the widgets 49 | mainSizer.Add(self.canvas, 1, wx.EXPAND) 50 | checkSizer.Add(toggleGrid, 0, wx.ALL, 5) 51 | checkSizer.Add(toggleLegend, 0, wx.ALL, 5) 52 | mainSizer.Add(checkSizer) 53 | panel.SetSizer(mainSizer) 54 | 55 | def onToggleGrid(self, event): 56 | """""" 57 | self.canvas.SetEnableGrid(event.IsChecked()) 58 | 59 | def onToggleLegend(self, event): 60 | """""" 61 | self.canvas.SetEnableLegend(event.IsChecked()) 62 | 63 | if __name__ == '__main__': 64 | app = wx.App(False) 65 | frame = MyGraph() 66 | frame.Show() 67 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_38_pyplot/data.txt: -------------------------------------------------------------------------------- 1 | # http://www.wunderground.com/history/airport/KMIW/2010/9/22/WeeklyHistory.html?format=1 2 | CDT,Max TemperatureF,Mean TemperatureF,Min TemperatureF,Max Dew PointF,MeanDew PointF,Min DewpointF,Max Humidity, Mean Humidity, Min Humidity, Max Sea Level PressureIn, Mean Sea Level PressureIn, Min Sea Level PressureIn, Max VisibilityMiles, Mean VisibilityMiles, Min VisibilityMiles, Max Wind SpeedMPH, Mean Wind SpeedMPH, Max Gust SpeedMPH,PrecipitationIn, CloudCover, Events
3 | 2010-9-19,56,52,47,55,49,44,100,97,93,30.21,30.17,30.11,10,5,2,14,9,20,0.34,8,Rain-Thunderstorm
4 | 2010-9-20,88,72,56,71,62,55,100,73,46,30.10,29.94,29.77,10,6,0,25,12,32,T,4,Fog-Rain
5 | 2010-9-21,75,70,64,66,64,63,93,83,73,29.89,29.83,29.75,10,7,0,22,7,30,1.79,5,Fog-Rain-Thunderstorm
6 | 2010-9-22,75,70,64,68,64,63,100,93,69,30.00,29.96,29.86,10,5,1,15,4,,0.26,8,Rain
7 | 8 | -------------------------------------------------------------------------------- /recipe_38_pyplot/plotting_25000_points.py: -------------------------------------------------------------------------------- 1 | import numpy as _Numeric 2 | import wx 3 | from wx.lib.plot import PlotCanvas, PlotGraphics, PolyLine, PolyMarker 4 | 5 | 6 | def drawLinePlot(): 7 | # 25,000 point line 8 | data1 = _Numeric.arange(5e5,1e6,10) 9 | data1.shape = (25000, 2) 10 | line1 = PolyLine(data1, legend='Wide Line', colour='green', width=5) 11 | 12 | # A few more points... 13 | markers2 = PolyMarker(data1, legend='Square', colour='blue', 14 | marker='square') 15 | return PlotGraphics([line1, markers2], "25,000 Points", "Value X", "") 16 | 17 | 18 | class MyGraph(wx.Frame): 19 | 20 | 21 | def __init__(self): 22 | wx.Frame.__init__(self, None, wx.ID_ANY, 23 | 'It Looks Like a Line Graph!') 24 | 25 | # Add a panel so it looks the correct on all platforms 26 | panel = wx.Panel(self, wx.ID_ANY) 27 | 28 | # create some sizers 29 | mainSizer = wx.BoxSizer(wx.VERTICAL) 30 | checkSizer = wx.BoxSizer(wx.HORIZONTAL) 31 | 32 | # create the widgets 33 | self.canvas = PlotCanvas(panel) 34 | self.canvas.Draw(drawLinePlot()) 35 | toggleGrid = wx.CheckBox(panel, label="Show Grid") 36 | toggleGrid.Bind(wx.EVT_CHECKBOX, self.onToggleGrid) 37 | toggleLegend = wx.CheckBox(panel, label="Show Legend") 38 | toggleLegend.Bind(wx.EVT_CHECKBOX, self.onToggleLegend) 39 | 40 | # layout the widgets 41 | mainSizer.Add(self.canvas, 1, wx.EXPAND) 42 | checkSizer.Add(toggleGrid, 0, wx.ALL, 5) 43 | checkSizer.Add(toggleLegend, 0, wx.ALL, 5) 44 | mainSizer.Add(checkSizer) 45 | panel.SetSizer(mainSizer) 46 | 47 | 48 | def onToggleGrid(self, event): 49 | """""" 50 | self.canvas.SetEnableGrid(event.IsChecked()) 51 | 52 | 53 | def onToggleLegend(self, event): 54 | """""" 55 | self.canvas.SetEnableLegend(event.IsChecked()) 56 | 57 | if __name__ == '__main__': 58 | app = wx.App(False) 59 | frame = MyGraph() 60 | frame.Show() 61 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_38_pyplot/plotting_saved_data.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx.lib.plot import PolyLine, PlotCanvas, PlotGraphics 3 | 4 | class MyGraph(wx.Frame): 5 | 6 | def __init__(self): 7 | wx.Frame.__init__(self, None, wx.ID_ANY, 8 | 'Plotting File Data') 9 | 10 | # Add a panel so it looks the correct on all platforms 11 | panel = wx.Panel(self, wx.ID_ANY) 12 | self.canvas = PlotCanvas(panel) 13 | self.canvas.Draw(self.createPlotGraphics()) 14 | 15 | sizer = wx.BoxSizer(wx.VERTICAL) 16 | sizer.Add(self.canvas, 1, wx.EXPAND) 17 | panel.SetSizer(sizer) 18 | 19 | def readFile(self): 20 | """ 21 | Reads the hard-coded file 22 | """ 23 | # normally you would want to pass a file path in, NOT hard code it! 24 | with open("data.txt") as fobj: 25 | # skip the first two lines of text in the file 26 | data = fobj.readlines()[2:-1] 27 | 28 | temps = [] 29 | for line in data: 30 | parts = line.split(",") 31 | date = parts[0].split("-") 32 | day = date[2] 33 | points = [(day, parts[3]), (day, parts[1])] 34 | temps.append(points) 35 | return temps 36 | 37 | def createPlotGraphics(self): 38 | """ 39 | Create the plot's graphics 40 | """ 41 | temps = self.readFile() 42 | lines = [] 43 | for temp in temps: 44 | tempInt = int(temp[1][1]) 45 | if tempInt < 60: 46 | color = "blue" 47 | elif tempInt >=60 and tempInt <= 75: 48 | color = "orange" 49 | else: 50 | color = "red" 51 | lines.append(PolyLine(temp, colour=color, width=10)) 52 | 53 | return PlotGraphics(lines, "Bar Graph of Temperatures", 54 | "Days", "Temperatures") 55 | 56 | if __name__ == '__main__': 57 | app = wx.App(False) 58 | frame = MyGraph() 59 | frame.Show() 60 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_38_pyplot/sin_cos.py: -------------------------------------------------------------------------------- 1 | import numpy as _Numeric 2 | import wx 3 | from wx.lib.plot import PlotCanvas, PlotGraphics, PolyLine, PolyMarker 4 | 5 | 6 | def drawSinCosWaves(): 7 | # 100 points sin function, plotted as green circles 8 | data1 = 2.*_Numeric.pi*_Numeric.arange(200)/200. 9 | data1.shape = (100, 2) 10 | data1[:,1] = _Numeric.sin(data1[:,0]) 11 | markers1 = PolyMarker(data1, legend='Green Markers', colour='green', marker='circle',size=1) 12 | 13 | # 50 points cos function, plotted as red line 14 | data1 = 2.*_Numeric.pi*_Numeric.arange(100)/100. 15 | data1.shape = (50,2) 16 | data1[:,1] = _Numeric.cos(data1[:,0]) 17 | lines = PolyLine(data1, legend= 'Red Line', colour='red') 18 | 19 | # A few more points... 20 | pi = _Numeric.pi 21 | markers2 = PolyMarker([(0., 0.), (pi/4., 1.), (pi/2, 0.), 22 | (3.*pi/4., -1)], legend='Cross Legend', colour='blue', 23 | marker='cross') 24 | 25 | return PlotGraphics([markers1, lines, markers2],"Graph Title", "X Axis", "Y Axis") 26 | 27 | 28 | class MyGraph(wx.Frame): 29 | 30 | 31 | def __init__(self): 32 | wx.Frame.__init__(self, None, wx.ID_ANY, 33 | 'Sin / Cos Plot') 34 | 35 | # Add a panel so it looks the correct on all platforms 36 | panel = wx.Panel(self, wx.ID_ANY) 37 | 38 | # create some sizers 39 | mainSizer = wx.BoxSizer(wx.VERTICAL) 40 | checkSizer = wx.BoxSizer(wx.HORIZONTAL) 41 | 42 | # create the widgets 43 | self.canvas = PlotCanvas(panel) 44 | self.canvas.Draw(drawSinCosWaves()) 45 | toggleGrid = wx.CheckBox(panel, label="Show Grid") 46 | toggleGrid.Bind(wx.EVT_CHECKBOX, self.onToggleGrid) 47 | toggleLegend = wx.CheckBox(panel, label="Show Legend") 48 | toggleLegend.Bind(wx.EVT_CHECKBOX, self.onToggleLegend) 49 | 50 | # layout the widgets 51 | mainSizer.Add(self.canvas, 1, wx.EXPAND) 52 | checkSizer.Add(toggleGrid, 0, wx.ALL, 5) 53 | checkSizer.Add(toggleLegend, 0, wx.ALL, 5) 54 | mainSizer.Add(checkSizer) 55 | panel.SetSizer(mainSizer) 56 | 57 | 58 | def onToggleGrid(self, event): 59 | """""" 60 | self.canvas.SetEnableGrid(event.IsChecked()) 61 | 62 | 63 | def onToggleLegend(self, event): 64 | """""" 65 | self.canvas.SetEnableLegend(event.IsChecked()) 66 | 67 | if __name__ == '__main__': 68 | app = wx.App(False) 69 | frame = MyGraph() 70 | frame.Show() 71 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_39_logging_textctrl/main.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import logging.config 3 | import wx 4 | 5 | 6 | class CustomConsoleHandler(logging.StreamHandler): 7 | """""" 8 | 9 | def __init__(self, textctrl): 10 | """""" 11 | logging.StreamHandler.__init__(self) 12 | self.textctrl = textctrl 13 | 14 | def emit(self, record): 15 | """Constructor""" 16 | msg = self.format(record) 17 | self.textctrl.WriteText(msg + "\n") 18 | self.flush() 19 | 20 | 21 | class MyPanel(wx.Panel): 22 | """""" 23 | 24 | def __init__(self, parent): 25 | """Constructor""" 26 | wx.Panel.__init__(self, parent) 27 | self.logger = logging.getLogger("wxApp") 28 | 29 | self.logger.info("Test from MyPanel __init__") 30 | 31 | logText = wx.TextCtrl( 32 | self, 33 | style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL) 34 | 35 | btn = wx.Button(self, label="Press Me") 36 | btn.Bind(wx.EVT_BUTTON, self.onPress) 37 | 38 | sizer = wx.BoxSizer(wx.VERTICAL) 39 | sizer.Add(logText, 1, wx.EXPAND|wx.ALL, 5) 40 | sizer.Add(btn, 0, wx.ALL, 5) 41 | self.SetSizer(sizer) 42 | 43 | txtHandler = CustomConsoleHandler(logText) 44 | self.logger.addHandler(txtHandler) 45 | 46 | def onPress(self, event): 47 | """ 48 | On the press of a button, log some messages 49 | """ 50 | self.logger.error("Error Will Robinson!") 51 | self.logger.info("Informational message") 52 | 53 | 54 | class MyFrame(wx.Frame): 55 | """""" 56 | 57 | def __init__(self): 58 | """Constructor""" 59 | wx.Frame.__init__(self, None, title="Logging test") 60 | panel = MyPanel(self) 61 | self.logger = logging.getLogger("wxApp") 62 | self.Show() 63 | 64 | 65 | def main(): 66 | """ 67 | Run the program 68 | """ 69 | dictLogConfig = { 70 | "version":1, 71 | "handlers":{ 72 | "fileHandler":{ 73 | "class":"logging.FileHandler", 74 | "formatter":"myFormatter", 75 | "filename":"test.log" 76 | }, 77 | "consoleHandler":{ 78 | "class":"logging.StreamHandler", 79 | "formatter":"myFormatter" 80 | } 81 | }, 82 | "loggers":{ 83 | "wxApp":{ 84 | "handlers":["fileHandler", "consoleHandler"], 85 | "level":"INFO", 86 | } 87 | }, 88 | 89 | "formatters":{ 90 | "myFormatter":{ 91 | "format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s" 92 | } 93 | } 94 | } 95 | logging.config.dictConfig(dictLogConfig) 96 | logger = logging.getLogger("wxApp") 97 | 98 | logger.info("This message came from main!") 99 | 100 | app = wx.App(False) 101 | frame = MyFrame() 102 | app.MainLoop() 103 | 104 | 105 | if __name__ == "__main__": 106 | main() -------------------------------------------------------------------------------- /recipe_3_embedding_image/custom_icon.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title='Custom Image') 7 | 8 | self.panel = wx.Panel(self, wx.ID_ANY) 9 | 10 | ico = wx.Icon('py.ico', wx.BITMAP_TYPE_ICO) 11 | self.SetIcon(ico) 12 | 13 | 14 | if __name__ == '__main__': 15 | app = wx.App(False) 16 | frame = MyForm().Show() 17 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_3_embedding_image/image_from_exe.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, title='Image Extractor') 7 | 8 | self.panel = wx.Panel(self) 9 | 10 | loc = wx.IconLocation(r'C:\Python35\python.exe', 0) 11 | self.SetIcon(wx.Icon(loc)) 12 | 13 | 14 | if __name__ == '__main__': 15 | app = wx.App(False) 16 | frame = MyForm().Show() 17 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_3_embedding_image/img_from_python_code.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import my_icon 3 | 4 | class MyForm(wx.Frame): 5 | 6 | def __init__(self): 7 | wx.Frame.__init__(self, None, title='Python Image Title') 8 | 9 | self.panel = wx.Panel(self, wx.ID_ANY) 10 | 11 | ico = my_icon.PyEmbeddedImage(my_icon.py) 12 | self.SetIcon(ico.data.GetIcon()) 13 | 14 | 15 | # Run the program 16 | if __name__ == '__main__': 17 | app = wx.App(False) 18 | frame = MyForm().Show() 19 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_3_embedding_image/py.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_3_embedding_image/py.ico -------------------------------------------------------------------------------- /recipe_40_redirect_stdout/main_non_thread_safe.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import wx 3 | 4 | class MyForm(wx.Frame): 5 | 6 | def __init__(self): 7 | wx.Frame.__init__(self, None, 8 | title="wxPython Redirect Tutorial") 9 | 10 | # Add a panel so it looks the correct on all platforms 11 | panel = wx.Panel(self, wx.ID_ANY) 12 | style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL 13 | log = wx.TextCtrl(panel, wx.ID_ANY, size=(300,100), 14 | style=style) 15 | btn = wx.Button(panel, wx.ID_ANY, 'Push me!') 16 | self.Bind(wx.EVT_BUTTON, self.onButton, btn) 17 | 18 | # Add widgets to a sizer 19 | sizer = wx.BoxSizer(wx.VERTICAL) 20 | sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5) 21 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 22 | panel.SetSizer(sizer) 23 | 24 | # redirect text here 25 | sys.stdout = log 26 | 27 | def onButton(self, event): 28 | print("You pressed the button!") 29 | 30 | 31 | if __name__ == "__main__": 32 | app = wx.App(False) 33 | frame = MyForm().Show() 34 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_40_redirect_stdout/main_non_thread_safe_phoenix.py: -------------------------------------------------------------------------------- 1 | # wxPython Phoenix 2 | 3 | import sys 4 | import wx 5 | 6 | class MyCustomTextCtrl(wx.TextCtrl): 7 | 8 | def __init__(self, *args, **kwargs): 9 | """ 10 | Initial the text control 11 | """ 12 | wx.TextCtrl.__init__(self, *args, **kwargs) 13 | 14 | def write(self, text): 15 | self.WriteText(text) 16 | 17 | 18 | class MyForm(wx.Frame): 19 | 20 | def __init__(self): 21 | wx.Frame.__init__(self, None, 22 | title="wxPython Redirect Tutorial") 23 | 24 | # Add a panel so it looks the correct on all platforms 25 | panel = wx.Panel(self, wx.ID_ANY) 26 | style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL 27 | log = MyCustomTextCtrl(panel, wx.ID_ANY, size=(300,100), 28 | style=style) 29 | btn = wx.Button(panel, wx.ID_ANY, 'Push me!') 30 | self.Bind(wx.EVT_BUTTON, self.onButton, btn) 31 | 32 | # Add widgets to a sizer 33 | sizer = wx.BoxSizer(wx.VERTICAL) 34 | sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5) 35 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 36 | panel.SetSizer(sizer) 37 | 38 | # redirect text here 39 | sys.stdout = log 40 | 41 | def onButton(self, event): 42 | print("You pressed the button!") 43 | 44 | 45 | if __name__ == "__main__": 46 | app = wx.App(False) 47 | frame = MyForm().Show() 48 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_40_redirect_stdout/main_thread_safe.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import wx 3 | 4 | 5 | class RedirectText(): 6 | 7 | def __init__(self, my_text_ctrl): 8 | self.out = my_text_ctrl 9 | 10 | def write(self,string): 11 | wx.CallAfter(self.out.WriteText, string) 12 | 13 | 14 | class MyForm(wx.Frame): 15 | 16 | def __init__(self): 17 | wx.Frame.__init__(self, None, title="wxPython Redirect Tutorial") 18 | 19 | # Add a panel so it looks the correct on all platforms 20 | panel = wx.Panel(self, wx.ID_ANY) 21 | log = wx.TextCtrl(panel, wx.ID_ANY, size=(300,100), 22 | style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL) 23 | btn = wx.Button(panel, wx.ID_ANY, 'Push me!') 24 | self.Bind(wx.EVT_BUTTON, self.onButton, btn) 25 | 26 | # Add widgets to a sizer 27 | sizer = wx.BoxSizer(wx.VERTICAL) 28 | sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5) 29 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 30 | panel.SetSizer(sizer) 31 | 32 | # redirect text here 33 | redir = RedirectText(log) 34 | sys.stdout = redir 35 | 36 | def onButton(self, event): 37 | print("You pressed the button!") 38 | 39 | 40 | if __name__ == "__main__": 41 | app = wx.App(False) 42 | frame = MyForm().Show() 43 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_41_simple_notebook/simple.py: -------------------------------------------------------------------------------- 1 | import random 2 | import wx 3 | 4 | 5 | class TabPanel(wx.Panel): 6 | 7 | def __init__(self, parent): 8 | """""" 9 | wx.Panel.__init__(self, parent=parent) 10 | 11 | colors = ["red", "blue", "gray", "yellow", "green"] 12 | self.SetBackgroundColour(random.choice(colors)) 13 | 14 | btn = wx.Button(self, label="Press Me") 15 | sizer = wx.BoxSizer(wx.VERTICAL) 16 | sizer.Add(btn, 0, wx.ALL, 10) 17 | self.SetSizer(sizer) 18 | 19 | 20 | class DemoFrame(wx.Frame): 21 | """ 22 | Frame that holds all other widgets 23 | """ 24 | 25 | def __init__(self): 26 | """Constructor""" 27 | wx.Frame.__init__(self, None, wx.ID_ANY, 28 | "Notebook Tutorial", 29 | size=(600,400) 30 | ) 31 | panel = wx.Panel(self) 32 | 33 | notebook = wx.Notebook(panel) 34 | tabOne = TabPanel(notebook) 35 | notebook.AddPage(tabOne, "Tab 1") 36 | 37 | tabTwo = TabPanel(notebook) 38 | notebook.AddPage(tabTwo, "Tab 2") 39 | 40 | sizer = wx.BoxSizer(wx.VERTICAL) 41 | sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5) 42 | panel.SetSizer(sizer) 43 | self.Layout() 44 | 45 | self.Show() 46 | 47 | 48 | if __name__ == "__main__": 49 | app = wx.App(False) 50 | frame = DemoFrame() 51 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_41_simple_notebook/simple_refactored.py: -------------------------------------------------------------------------------- 1 | import random 2 | import wx 3 | 4 | 5 | class TabPanel(wx.Panel): 6 | """ 7 | The panel class to derive the tabs of the Notebook from 8 | """ 9 | 10 | def __init__(self, parent): 11 | """""" 12 | wx.Panel.__init__(self, parent=parent) 13 | 14 | colors = ["red", "blue", "gray", "yellow", "green"] 15 | self.SetBackgroundColour(random.choice(colors)) 16 | 17 | btn = wx.Button(self, label="Press Me") 18 | sizer = wx.BoxSizer(wx.VERTICAL) 19 | sizer.Add(btn, 0, wx.ALL, 10) 20 | self.SetSizer(sizer) 21 | 22 | 23 | class DemoNotebook(wx.Notebook): 24 | """ 25 | Our Notebook class 26 | """ 27 | 28 | def __init__(self, parent): 29 | wx.Notebook.__init__(self, parent) 30 | 31 | tabOne = TabPanel(self) 32 | self.AddPage(tabOne, "Tab 1") 33 | 34 | tabTwo = TabPanel(self) 35 | self.AddPage(tabTwo, "Tab 2") 36 | 37 | 38 | class DemoPanel(wx.Panel): 39 | """ 40 | The main panel used by the frame 41 | """ 42 | 43 | def __init__(self, parent): 44 | """""" 45 | wx.Panel.__init__(self, parent=parent) 46 | 47 | notebook = DemoNotebook(self) 48 | 49 | sizer = wx.BoxSizer(wx.VERTICAL) 50 | sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5) 51 | self.SetSizer(sizer) 52 | 53 | 54 | class DemoFrame(wx.Frame): 55 | """ 56 | Frame that holds all other widgets 57 | """ 58 | 59 | def __init__(self): 60 | """Constructor""" 61 | wx.Frame.__init__(self, None, wx.ID_ANY, 62 | "Notebook Tutorial", 63 | size=(600,400) 64 | ) 65 | panel = DemoPanel(self) 66 | 67 | self.Layout() 68 | 69 | self.Show() 70 | 71 | 72 | if __name__ == "__main__": 73 | app = wx.App(False) 74 | frame = DemoFrame() 75 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_42_singleton_frame/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MyPanel(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """Constructor""" 9 | wx.Panel.__init__(self, parent) 10 | 11 | 12 | class SingleInstanceFrame(wx.Frame): 13 | """""" 14 | 15 | instance = None 16 | init = 0 17 | 18 | def __new__(self, *args, **kwargs): 19 | """""" 20 | if self.instance is None: 21 | self.instance = wx.Frame.__new__(self) 22 | elif not self.instance: 23 | self.instance = wx.Frame.__new__(self) 24 | 25 | return self.instance 26 | 27 | def __init__(self): 28 | """Constructor""" 29 | print(id(self)) 30 | if self.init: 31 | return 32 | self.init = 1 33 | 34 | wx.Frame.__init__(self, None, title="Single Instance Frame") 35 | panel = MyPanel(self) 36 | self.Show() 37 | 38 | 39 | class MainFrame(wx.Frame): 40 | """""" 41 | 42 | def __init__(self): 43 | """Constructor""" 44 | wx.Frame.__init__(self, None, title="Main Frame") 45 | panel = MyPanel(self) 46 | btn = wx.Button(panel, label="Open Frame") 47 | btn.Bind(wx.EVT_BUTTON, self.open_frame) 48 | self.Show() 49 | 50 | def open_frame(self, event): 51 | frame = SingleInstanceFrame() 52 | 53 | 54 | if __name__ == '__main__': 55 | app = wx.App(False) 56 | frame = MainFrame() 57 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_43_storing_objects/objects_in_combobox.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class Car: 5 | """""" 6 | 7 | def __init__(self, id, model, make, year): 8 | """Constructor""" 9 | self.id = id 10 | self.model = model 11 | self.make = make 12 | self.year = year 13 | 14 | 15 | class MyForm(wx.Frame): 16 | 17 | def __init__(self): 18 | wx.Frame.__init__(self, None, title="Tutorial") 19 | 20 | panel = wx.Panel(self, wx.ID_ANY) 21 | 22 | cars = [Car(0, "Ford", "F-150", "2008"), 23 | Car(1, "Chevrolet", "Camaro", "2010"), 24 | Car(2, "Nissan", "370Z", "2005")] 25 | 26 | sampleList = [] 27 | self.cb = wx.ComboBox(panel, 28 | size=wx.DefaultSize, 29 | choices=sampleList) 30 | self.widgetMaker(self.cb, cars) 31 | 32 | sizer = wx.BoxSizer(wx.VERTICAL) 33 | sizer.Add(self.cb, 0, wx.ALL, 5) 34 | panel.SetSizer(sizer) 35 | 36 | def widgetMaker(self, widget, objects): 37 | """""" 38 | for obj in objects: 39 | widget.Append(obj.make, obj) 40 | widget.Bind(wx.EVT_COMBOBOX, self.onSelect) 41 | 42 | def onSelect(self, event): 43 | """""" 44 | print("You selected: " + self.cb.GetStringSelection()) 45 | obj = self.cb.GetClientData(self.cb.GetSelection()) 46 | text = """ 47 | The object's attributes are: 48 | %s %s %s %s 49 | 50 | """ % (obj.id, obj.make, obj.model, obj.year) 51 | print(text) 52 | 53 | 54 | if __name__ == "__main__": 55 | app = wx.App(False) 56 | frame = MyForm() 57 | frame.Show() 58 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_43_storing_objects/objects_in_listbox.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class Car: 5 | """""" 6 | 7 | def __init__(self, id, model, make, year): 8 | """Constructor""" 9 | self.id = id 10 | self.model = model 11 | self.make = make 12 | self.year = year 13 | 14 | 15 | class MyForm(wx.Frame): 16 | 17 | def __init__(self): 18 | wx.Frame.__init__(self, None, title="ListBox Obj Tutorial") 19 | 20 | panel = wx.Panel(self, wx.ID_ANY) 21 | 22 | ford = Car(0, "Ford", "F-150", "2008") 23 | chevy = Car(1, "Chevrolet", "Camaro", "2010") 24 | nissan = Car(2, "Nissan", "370Z", "2005") 25 | 26 | sampleList = [] 27 | lb = wx.ListBox(panel, 28 | size=wx.DefaultSize, 29 | choices=sampleList) 30 | self.lb = lb 31 | lb.Append(ford.make, ford) 32 | lb.Append(chevy.make, chevy) 33 | lb.Append(nissan.make, nissan) 34 | lb.Bind(wx.EVT_LISTBOX, self.onSelect) 35 | 36 | sizer = wx.BoxSizer(wx.VERTICAL) 37 | sizer.Add(lb, 0, wx.ALL, 5) 38 | panel.SetSizer(sizer) 39 | 40 | def onSelect(self, event): 41 | """""" 42 | selection = self.lb.GetStringSelection() 43 | if selection: 44 | print("You selected: " + selection) 45 | obj = self.lb.GetClientData(self.lb.GetSelection()) 46 | text = """ 47 | The object's attributes are: 48 | %s %s %s %s 49 | 50 | """ % (obj.id, obj.make, obj.model, obj.year) 51 | print(text) 52 | 53 | 54 | if __name__ == "__main__": 55 | app = wx.App(False) 56 | frame = MyForm() 57 | frame.Show() 58 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_44_syncing_grid_scroll/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.grid as gridlib 3 | 4 | 5 | class ScrollSync(object): 6 | def __init__(self, panel1, panel2): 7 | self.panel1 = panel1 8 | self.panel2 = panel2 9 | self.panel1.grid.Bind(wx.EVT_SCROLLWIN, self.onScrollWin1) 10 | self.panel2.grid.Bind(wx.EVT_SCROLLWIN, self.onScrollWin2) 11 | 12 | def onScrollWin1(self, event): 13 | if event.Orientation == wx.SB_HORIZONTAL: 14 | self.panel2.grid.Scroll(event.Position, -1) 15 | else: 16 | self.panel2.grid.Scroll(-1, event.Position) 17 | event.Skip() 18 | 19 | def onScrollWin2(self, event): 20 | if event.Orientation == wx.SB_HORIZONTAL: 21 | self.panel1.grid.Scroll(event.Position, -1) 22 | else: 23 | self.panel1.grid.Scroll(-1, event.Position) 24 | event.Skip() 25 | 26 | 27 | class GridPanel(wx.Panel): 28 | """""" 29 | 30 | def __init__(self, parent): 31 | """Constructor""" 32 | wx.Panel.__init__(self, parent) 33 | self.grid = gridlib.Grid(self, style=wx.BORDER_SUNKEN) 34 | self.grid.CreateGrid(25,8) 35 | 36 | sizer = wx.BoxSizer(wx.VERTICAL) 37 | sizer.Add(self.grid, 1, wx.EXPAND) 38 | self.SetSizer(sizer) 39 | 40 | 41 | class MainPanel(wx.Panel): 42 | """""" 43 | 44 | def __init__(self, parent): 45 | """Constructor""" 46 | wx.Panel.__init__(self, parent) 47 | 48 | 49 | split = wx.SplitterWindow(self) 50 | 51 | panelOne = GridPanel(split) 52 | panelTwo = GridPanel(split) 53 | ScrollSync(panelOne, panelTwo) 54 | 55 | split.SplitVertically(panelOne, panelTwo) 56 | split.SetSashGravity(0.5) 57 | 58 | sizer = wx.BoxSizer(wx.VERTICAL) 59 | sizer.Add(split, 1, wx.EXPAND) 60 | self.SetSizer(sizer) 61 | 62 | 63 | class MainFrame(wx.Frame): 64 | """""" 65 | 66 | def __init__(self): 67 | """Constructor""" 68 | wx.Frame.__init__(self, None, title="Sync Grids", 69 | size=(800,400)) 70 | panel = MainPanel(self) 71 | self.Show() 72 | 73 | 74 | if __name__ == "__main__": 75 | app = wx.App(False) 76 | frame = MainFrame() 77 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_45_timers/multiple_timers.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import time 3 | 4 | TIMER_ID1 = 2000 5 | TIMER_ID2 = 2001 6 | 7 | class MyForm(wx.Frame): 8 | 9 | def __init__(self): 10 | wx.Frame.__init__(self, None, title="Timer Tutorial 2") 11 | 12 | panel = wx.Panel(self, wx.ID_ANY) 13 | 14 | self.timer = wx.Timer(self, id=TIMER_ID1) 15 | self.Bind(wx.EVT_TIMER, self.update, self.timer) 16 | self.timer2 = wx.Timer(self, id=TIMER_ID2) 17 | self.Bind(wx.EVT_TIMER, self.update, self.timer2) 18 | 19 | self.toggleBtn = wx.Button(panel, wx.ID_ANY, "Start Timer 1") 20 | self.toggleBtn.Bind(wx.EVT_BUTTON, self.onStartTimerOne) 21 | self.toggleBtn2 = wx.Button(panel, wx.ID_ANY, "Start Timer 2") 22 | self.toggleBtn2.Bind(wx.EVT_BUTTON, self.onStartTimerOne) 23 | 24 | sizer = wx.BoxSizer(wx.VERTICAL) 25 | sizer.Add(self.toggleBtn, 0, wx.ALL|wx.CENTER, 5) 26 | sizer.Add(self.toggleBtn2, 0, wx.ALL|wx.CENTER, 5) 27 | panel.SetSizer(sizer) 28 | 29 | def onStartTimerOne(self, event): 30 | buttonObj = event.GetEventObject() 31 | btnLabel = buttonObj.GetLabel() 32 | timerNum = int(btnLabel[-1:]) 33 | print(timerNum) 34 | 35 | if btnLabel == "Start Timer %s" % timerNum: 36 | if timerNum == 1: 37 | print("starting timer 1...") 38 | self.timer.Start(1000) 39 | else: 40 | print("starting timer 2...") 41 | self.timer2.Start(3000) 42 | buttonObj.SetLabel("Stop Timer %s" % timerNum) 43 | else: 44 | if timerNum == 1: 45 | self.timer.Stop() 46 | print("timer 1 stopped!") 47 | else: 48 | self.timer2.Stop() 49 | print("timer 2 stopped!") 50 | buttonObj.SetLabel("Start Timer %s" % timerNum) 51 | 52 | def update(self, event): 53 | timerId = event.GetId() 54 | if timerId == TIMER_ID1: 55 | print("\ntimer 1 updated: ", time.ctime()) 56 | else: 57 | print("\ntimer 2 updated: ", time.ctime()) 58 | 59 | 60 | # Run the program 61 | if __name__ == "__main__": 62 | app = wx.App() 63 | frame = MyForm().Show() 64 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_45_timers/multiple_timers_2.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import time 3 | 4 | class MyForm(wx.Frame): 5 | 6 | def __init__(self): 7 | wx.Frame.__init__(self, None, title="Timer Tutorial 2") 8 | 9 | panel = wx.Panel(self, wx.ID_ANY) 10 | 11 | self.timer = wx.Timer(self, wx.ID_ANY) 12 | self.Bind(wx.EVT_TIMER, self.update, self.timer) 13 | self.timer2 = wx.Timer(self, wx.ID_ANY) 14 | self.Bind(wx.EVT_TIMER, self.update, self.timer2) 15 | 16 | self.toggleBtn = wx.Button(panel, wx.ID_ANY, "Start Timer 1") 17 | self.toggleBtn.Bind(wx.EVT_BUTTON, self.onStartTimer) 18 | self.toggleBtn2 = wx.Button(panel, wx.ID_ANY, "Start Timer 2") 19 | self.toggleBtn2.Bind(wx.EVT_BUTTON, self.onStartTimer) 20 | 21 | sizer = wx.BoxSizer(wx.VERTICAL) 22 | sizer.Add(self.toggleBtn, 0, wx.ALL|wx.CENTER, 5) 23 | sizer.Add(self.toggleBtn2, 0, wx.ALL|wx.CENTER, 5) 24 | panel.SetSizer(sizer) 25 | 26 | # Each value in the following dict is formatted as follows: 27 | # (timerNum, timerObj, secs between timer events) 28 | self.objDict = {self.toggleBtn: (1, self.timer, 1000), 29 | self.toggleBtn2: (2, self.timer2, 3000)} 30 | 31 | def onStartTimer(self, event): 32 | btn = event.GetEventObject() 33 | timerNum, timer, secs = self.objDict[btn] 34 | if timer.IsRunning(): 35 | timer.Stop() 36 | btn.SetLabel("Start Timer %s" % timerNum) 37 | print("timer %s stopped!" % timerNum) 38 | else: 39 | print("starting timer %s..." % timerNum) 40 | timer.Start(secs) 41 | btn.SetLabel("Stop Timer %s" % timerNum) 42 | 43 | def update(self, event): 44 | timerId = event.GetId() 45 | if timerId == self.timer.GetId(): 46 | print("\ntimer 1 updated: ", time.ctime()) 47 | else: 48 | print ("\ntimer 2 updated: ", time.ctime()) 49 | 50 | 51 | # Run the program 52 | if __name__ == "__main__": 53 | app = wx.App() 54 | frame = MyForm().Show() 55 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_45_timers/simple_timer.py: -------------------------------------------------------------------------------- 1 | import time 2 | import wx 3 | 4 | class MyForm(wx.Frame): 5 | 6 | def __init__(self): 7 | wx.Frame.__init__(self, None, title="Timer Tutorial 1", 8 | size=(500,500)) 9 | 10 | panel = wx.Panel(self, wx.ID_ANY) 11 | 12 | self.timer = wx.Timer(self) 13 | self.Bind(wx.EVT_TIMER, self.update, self.timer) 14 | 15 | self.toggleBtn = wx.Button(panel, wx.ID_ANY, "Start") 16 | self.toggleBtn.Bind(wx.EVT_BUTTON, self.onToggle) 17 | 18 | def onToggle(self, event): 19 | btnLabel = self.toggleBtn.GetLabel() 20 | if btnLabel == "Start": 21 | print("starting timer...") 22 | self.timer.Start(1000) 23 | self.toggleBtn.SetLabel("Stop") 24 | else: 25 | print("timer stopped!") 26 | self.timer.Stop() 27 | self.toggleBtn.SetLabel("Start") 28 | 29 | def update(self, event): 30 | print("\nupdated: ", time.ctime()) 31 | 32 | 33 | # Run the program 34 | if __name__ == "__main__": 35 | app = wx.App(True) 36 | frame = MyForm().Show() 37 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_45_timers/simple_timer_2.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import time 3 | 4 | class MyForm(wx.Frame): 5 | 6 | def __init__(self): 7 | wx.Frame.__init__(self, None, title="Timer Tutorial 1", 8 | size=(500,500)) 9 | 10 | panel = wx.Panel(self, wx.ID_ANY) 11 | 12 | self.timer = wx.Timer(self) 13 | self.Bind(wx.EVT_TIMER, self.update, self.timer) 14 | 15 | self.toggleBtn = wx.Button(panel, wx.ID_ANY, "Start") 16 | self.toggleBtn.Bind(wx.EVT_BUTTON, self.onToggle) 17 | 18 | def onToggle(self, event): 19 | if self.timer.IsRunning(): 20 | self.timer.Stop() 21 | self.toggleBtn.SetLabel("Start") 22 | print("timer stopped!") 23 | else: 24 | print("starting timer...") 25 | self.timer.Start(1000) 26 | self.toggleBtn.SetLabel("Stop") 27 | 28 | def update(self, event): 29 | print("\nupdated: ", time.ctime()) 30 | 31 | 32 | # Run the program 33 | if __name__ == "__main__": 34 | app = wx.App(True) 35 | frame = MyForm().Show() 36 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_46_update_progress_thread/main_2.8.py: -------------------------------------------------------------------------------- 1 | # This code works with wxPython 2.8.12 and Python 2 2 | 3 | import time 4 | import wx 5 | 6 | from threading import Thread 7 | from wx.lib.pubsub import Publisher 8 | 9 | 10 | class TestThread(Thread): 11 | """Test Worker Thread Class.""" 12 | 13 | def __init__(self): 14 | """Init Worker Thread Class.""" 15 | Thread.__init__(self) 16 | self.start() # start the thread 17 | 18 | def run(self): 19 | """Run Worker Thread.""" 20 | # This is the code executing in the new thread. 21 | for i in range(20): 22 | time.sleep(1) 23 | wx.CallAfter(Publisher().sendMessage, "update", "") 24 | 25 | 26 | class MyProgressDialog(wx.Dialog): 27 | """""" 28 | 29 | def __init__(self): 30 | """Constructor""" 31 | wx.Dialog.__init__(self, None, title="Progress") 32 | self.count = 0 33 | 34 | self.progress = wx.Gauge(self, range=20) 35 | 36 | sizer = wx.BoxSizer(wx.VERTICAL) 37 | sizer.Add(self.progress, 0, wx.EXPAND) 38 | self.SetSizer(sizer) 39 | 40 | # create a pubsub listener 41 | Publisher().subscribe(self.updateProgress, "update") 42 | 43 | def updateProgress(self, msg): 44 | """ 45 | Update the progress bar 46 | """ 47 | self.count += 1 48 | 49 | if self.count >= 20: 50 | self.Destroy() 51 | 52 | self.progress.SetValue(self.count) 53 | 54 | 55 | class MyFrame(wx.Frame): 56 | 57 | def __init__(self): 58 | wx.Frame.__init__(self, None, title="Progress Bar Tutorial") 59 | 60 | # Add a panel so it looks the correct on all platforms 61 | panel = wx.Panel(self, wx.ID_ANY) 62 | self.btn = btn = wx.Button(panel, label="Start Thread") 63 | btn.Bind(wx.EVT_BUTTON, self.onButton) 64 | 65 | sizer = wx.BoxSizer(wx.VERTICAL) 66 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 67 | panel.SetSizer(sizer) 68 | 69 | def onButton(self, event): 70 | """ 71 | Runs the thread 72 | """ 73 | btn = event.GetEventObject() 74 | btn.Disable() 75 | 76 | TestThread() 77 | dlg = MyProgressDialog() 78 | dlg.ShowModal() 79 | 80 | btn.Enable() 81 | 82 | # Run the program 83 | if __name__ == "__main__": 84 | app = wx.App(False) 85 | frame = MyFrame() 86 | frame.Show() 87 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_46_update_progress_thread/main_3.0.py: -------------------------------------------------------------------------------- 1 | # This code works for wxPython 3.0+ and Phoenix 2 | # So you can run this code with Python 2 or 3 3 | 4 | import time 5 | import wx 6 | 7 | from threading import Thread 8 | from wx.lib.pubsub import pub 9 | 10 | 11 | class TestThread(Thread): 12 | """Test Worker Thread Class.""" 13 | 14 | def __init__(self): 15 | """Init Worker Thread Class.""" 16 | Thread.__init__(self) 17 | self.start() # start the thread 18 | 19 | def run(self): 20 | """Run Worker Thread.""" 21 | # This is the code executing in the new thread. 22 | for i in range(20): 23 | time.sleep(1) 24 | wx.CallAfter(pub.sendMessage, "update", msg="") 25 | 26 | 27 | class MyProgressDialog(wx.Dialog): 28 | """""" 29 | 30 | def __init__(self): 31 | """Constructor""" 32 | wx.Dialog.__init__(self, None, title="Progress") 33 | self.count = 0 34 | 35 | self.progress = wx.Gauge(self, range=20) 36 | 37 | sizer = wx.BoxSizer(wx.VERTICAL) 38 | sizer.Add(self.progress, 0, wx.EXPAND) 39 | self.SetSizer(sizer) 40 | 41 | # create a pubsub receiver 42 | pub.subscribe(self.updateProgress, "update") 43 | 44 | def updateProgress(self, msg): 45 | """""" 46 | self.count += 1 47 | 48 | if self.count >= 20: 49 | self.Destroy() 50 | 51 | self.progress.SetValue(self.count) 52 | 53 | 54 | class MyForm(wx.Frame): 55 | 56 | def __init__(self): 57 | wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") 58 | 59 | # Add a panel so it looks the correct on all platforms 60 | panel = wx.Panel(self, wx.ID_ANY) 61 | self.btn = btn = wx.Button(panel, label="Start Thread") 62 | btn.Bind(wx.EVT_BUTTON, self.onButton) 63 | 64 | sizer = wx.BoxSizer(wx.VERTICAL) 65 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 66 | panel.SetSizer(sizer) 67 | 68 | def onButton(self, event): 69 | """ 70 | Runs the thread 71 | """ 72 | btn = event.GetEventObject() 73 | btn.Disable() 74 | 75 | TestThread() 76 | dlg = MyProgressDialog() 77 | dlg.ShowModal() 78 | 79 | btn.Enable() 80 | 81 | 82 | # Run the program 83 | if __name__ == "__main__": 84 | app = wx.App(False) 85 | frame = MyForm().Show() 86 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_47_wx_and_threads/main.py: -------------------------------------------------------------------------------- 1 | # wxPython 3.0 and Phoenix 2 | 3 | import time 4 | import wx 5 | 6 | from threading import Thread 7 | from wx.lib.pubsub import pub 8 | 9 | 10 | class TestThread(Thread): 11 | """Test Worker Thread Class.""" 12 | 13 | def __init__(self): 14 | """Init Worker Thread Class.""" 15 | Thread.__init__(self) 16 | self.start() # start the thread 17 | 18 | def run(self): 19 | """Run Worker Thread.""" 20 | # This is the code executing in the new thread. 21 | for i in range(6): 22 | time.sleep(10) 23 | wx.CallAfter(self.postTime, i) 24 | time.sleep(5) 25 | wx.CallAfter(pub.sendMessage, "update", msg="Thread finished!") 26 | 27 | def postTime(self, amt): 28 | """ 29 | Send time to GUI 30 | """ 31 | amtOfTime = (amt + 1) * 10 32 | pub.sendMessage("update", msg=amtOfTime) 33 | 34 | 35 | class MyForm(wx.Frame): 36 | 37 | def __init__(self): 38 | wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") 39 | 40 | # Add a panel so it looks the correct on all platforms 41 | panel = wx.Panel(self, wx.ID_ANY) 42 | self.displayLbl = wx.StaticText(panel, 43 | label="Amount of time since thread started goes here") 44 | self.btn = btn = wx.Button(panel, label="Start Thread") 45 | 46 | btn.Bind(wx.EVT_BUTTON, self.onButton) 47 | 48 | sizer = wx.BoxSizer(wx.VERTICAL) 49 | sizer.Add(self.displayLbl, 0, wx.ALL|wx.CENTER, 5) 50 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 51 | panel.SetSizer(sizer) 52 | 53 | # create a pubsub receiver 54 | pub.subscribe(self.updateDisplay, "update") 55 | 56 | def onButton(self, event): 57 | """ 58 | Runs the thread 59 | """ 60 | TestThread() 61 | self.displayLbl.SetLabel("Thread started!") 62 | btn = event.GetEventObject() 63 | btn.Disable() 64 | 65 | def updateDisplay(self, msg): 66 | """ 67 | Receives data from thread and updates the display 68 | """ 69 | t = msg 70 | if isinstance(t, int): 71 | self.displayLbl.SetLabel("Time since thread started: %s seconds" % t) 72 | else: 73 | self.displayLbl.SetLabel("%s" % t) 74 | self.btn.Enable() 75 | 76 | 77 | # Run the program 78 | if __name__ == "__main__": 79 | app = wx.App(False) 80 | frame = MyForm().Show() 81 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_47_wx_and_threads/main_legacy.py: -------------------------------------------------------------------------------- 1 | # wxPython 2.8.12 2 | 3 | import time 4 | import wx 5 | 6 | from threading import Thread 7 | from wx.lib.pubsub import Publisher 8 | 9 | 10 | class TestThread(Thread): 11 | """Test Worker Thread Class.""" 12 | 13 | def __init__(self): 14 | """Init Worker Thread Class.""" 15 | Thread.__init__(self) 16 | self.start() # start the thread 17 | 18 | def run(self): 19 | """Run Worker Thread.""" 20 | # This is the code executing in the new thread. 21 | for i in range(6): 22 | time.sleep(10) 23 | wx.CallAfter(self.postTime, i) 24 | time.sleep(5) 25 | wx.CallAfter(Publisher().sendMessage, "update", "Thread finished!") 26 | 27 | def postTime(self, amt): 28 | """ 29 | Send time to GUI 30 | """ 31 | amtOfTime = (amt + 1) * 10 32 | Publisher().sendMessage("update", amtOfTime) 33 | 34 | 35 | class MyForm(wx.Frame): 36 | 37 | def __init__(self): 38 | wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") 39 | 40 | # Add a panel so it looks the correct on all platforms 41 | panel = wx.Panel(self, wx.ID_ANY) 42 | self.displayLbl = wx.StaticText(panel, 43 | label="Amount of time since thread started goes here") 44 | self.btn = btn = wx.Button(panel, label="Start Thread") 45 | 46 | btn.Bind(wx.EVT_BUTTON, self.onButton) 47 | 48 | sizer = wx.BoxSizer(wx.VERTICAL) 49 | sizer.Add(self.displayLbl, 0, wx.ALL|wx.CENTER, 5) 50 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 51 | panel.SetSizer(sizer) 52 | 53 | # create a pubsub receiver 54 | Publisher().subscribe(self.updateDisplay, "update") 55 | 56 | def onButton(self, event): 57 | """ 58 | Runs the thread 59 | """ 60 | TestThread() 61 | self.displayLbl.SetLabel("Thread started!") 62 | btn = event.GetEventObject() 63 | btn.Disable() 64 | 65 | def updateDisplay(self, msg): 66 | """ 67 | Receives data from thread and updates the display 68 | """ 69 | t = msg.data 70 | if isinstance(t, int): 71 | self.displayLbl.SetLabel("Time since thread started: %s seconds" % t) 72 | else: 73 | self.displayLbl.SetLabel("%s" % t) 74 | self.btn.Enable() 75 | 76 | 77 | # Run the program 78 | if __name__ == "__main__": 79 | app = wx.App(False) 80 | frame = MyForm().Show() 81 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_47_wx_and_threads/post_event_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | import wx 3 | 4 | from threading import Thread 5 | 6 | # Define notification event for thread completion 7 | EVT_RESULT_ID = wx.NewId() 8 | 9 | def EVT_RESULT(win, func): 10 | """Define Result Event.""" 11 | win.Connect(-1, -1, EVT_RESULT_ID, func) 12 | 13 | class ResultEvent(wx.PyEvent): 14 | """Simple event to carry arbitrary result data.""" 15 | def __init__(self, data): 16 | """Init Result Event.""" 17 | wx.PyEvent.__init__(self) 18 | self.SetEventType(EVT_RESULT_ID) 19 | self.data = data 20 | 21 | 22 | class TestThread(Thread): 23 | """Test Worker Thread Class.""" 24 | 25 | def __init__(self, wxObject): 26 | """Init Worker Thread Class.""" 27 | Thread.__init__(self) 28 | self.wxObject = wxObject 29 | self.start() # start the thread 30 | 31 | def run(self): 32 | """Run Worker Thread.""" 33 | # This is the code executing in the new thread. 34 | for i in range(6): 35 | time.sleep(10) 36 | amtOfTime = (i + 1) * 10 37 | wx.PostEvent(self.wxObject, ResultEvent(amtOfTime)) 38 | time.sleep(5) 39 | wx.PostEvent(self.wxObject, ResultEvent("Thread finished!")) 40 | 41 | 42 | class MyForm(wx.Frame): 43 | 44 | def __init__(self): 45 | wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") 46 | 47 | # Add a panel so it looks the correct on all platforms 48 | panel = wx.Panel(self, wx.ID_ANY) 49 | self.displayLbl = wx.StaticText(panel, label="Amount of time since thread started goes here") 50 | self.btn = btn = wx.Button(panel, label="Start Thread") 51 | 52 | btn.Bind(wx.EVT_BUTTON, self.onButton) 53 | 54 | sizer = wx.BoxSizer(wx.VERTICAL) 55 | sizer.Add(self.displayLbl, 0, wx.ALL|wx.CENTER, 5) 56 | sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 57 | panel.SetSizer(sizer) 58 | 59 | # Set up event handler for any worker thread results 60 | EVT_RESULT(self, self.updateDisplay) 61 | 62 | def onButton(self, event): 63 | """ 64 | Runs the thread 65 | """ 66 | TestThread(self) 67 | self.displayLbl.SetLabel("Thread started!") 68 | btn = event.GetEventObject() 69 | btn.Disable() 70 | 71 | def updateDisplay(self, msg): 72 | """ 73 | Receives data from thread and updates the display 74 | """ 75 | t = msg.data 76 | if isinstance(t, int): 77 | self.displayLbl.SetLabel("Time since thread started: %s seconds" % t) 78 | else: 79 | self.displayLbl.SetLabel("%s" % t) 80 | self.btn.Enable() 81 | 82 | 83 | # Run the program 84 | if __name__ == "__main__": 85 | app = wx.App(False) 86 | frame = MyForm().Show() 87 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.1/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import wx 3 | from wx.lib.softwareupdate import SoftwareUpdate 4 | 5 | 6 | class PhotoCtrl(wx.App, SoftwareUpdate): 7 | """ 8 | The Photo Viewer App Class 9 | """ 10 | 11 | def __init__(self, redirect=False, filename=None): 12 | wx.App.__init__(self, redirect, filename) 13 | 14 | BASEURL = "http://127.0.0.1:8000" 15 | self.InitUpdates(BASEURL, 16 | BASEURL + "/" + 'ChangeLog.txt') 17 | self.SetAppDisplayName('Image Viewer') 18 | self.CheckForUpdate() 19 | 20 | self.frame = wx.Frame(None, title='Photo Control') 21 | 22 | self.panel = wx.Panel(self.frame) 23 | 24 | self.PhotoMaxSize = 500 25 | 26 | self.createWidgets() 27 | self.frame.Show() 28 | 29 | def createWidgets(self): 30 | instructions = 'Browse for an image' 31 | img = wx.Image(240,240) 32 | self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY, 33 | wx.Bitmap(img)) 34 | 35 | instructLbl = wx.StaticText(self.panel, label=instructions) 36 | self.photoTxt = wx.TextCtrl(self.panel, size=(200,-1)) 37 | browseBtn = wx.Button(self.panel, label='Browse') 38 | browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse) 39 | 40 | self.mainSizer = wx.BoxSizer(wx.VERTICAL) 41 | self.sizer = wx.BoxSizer(wx.HORIZONTAL) 42 | 43 | self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY), 44 | 0, wx.ALL|wx.EXPAND, 5) 45 | self.mainSizer.Add(instructLbl, 0, wx.ALL, 5) 46 | self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5) 47 | self.sizer.Add(self.photoTxt, 0, wx.ALL, 5) 48 | self.sizer.Add(browseBtn, 0, wx.ALL, 5) 49 | self.mainSizer.Add(self.sizer, 0, wx.ALL, 5) 50 | 51 | self.panel.SetSizer(self.mainSizer) 52 | self.mainSizer.Fit(self.frame) 53 | 54 | self.panel.Layout() 55 | 56 | def onBrowse(self, event): 57 | """ 58 | Browse for file 59 | """ 60 | wildcard = "JPEG files (*.jpg)|*.jpg" 61 | dialog = wx.FileDialog(None, "Choose a file", 62 | wildcard=wildcard, 63 | style=wx.FD_OPEN) 64 | if dialog.ShowModal() == wx.ID_OK: 65 | self.photoTxt.SetValue(dialog.GetPath()) 66 | dialog.Destroy() 67 | self.onView() 68 | 69 | def onView(self): 70 | """ 71 | Attempts to load the image and display it 72 | """ 73 | filepath = self.photoTxt.GetValue() 74 | img = wx.Image(filepath, wx.BITMAP_TYPE_ANY) 75 | # scale the image, preserving the aspect ratio 76 | W = img.GetWidth() 77 | H = img.GetHeight() 78 | if W > H: 79 | NewW = self.PhotoMaxSize 80 | NewH = self.PhotoMaxSize * H / W 81 | else: 82 | NewH = self.PhotoMaxSize 83 | NewW = self.PhotoMaxSize * W / H 84 | img = img.Scale(NewW,NewH) 85 | 86 | self.imageCtrl.SetBitmap(wx.Bitmap(img)) 87 | self.panel.Refresh() 88 | self.mainSizer.Fit(self.frame) 89 | 90 | 91 | if __name__ == '__main__': 92 | app = PhotoCtrl() 93 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.1/mondrian.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_48_updating_your_app/Releases/image_viewer-0.0.1/mondrian.icns -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.1/mondrian.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_48_updating_your_app/Releases/image_viewer-0.0.1/mondrian.ico -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.1/setup.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | from esky import bdist_esky 3 | from setuptools import setup 4 | 5 | import version 6 | 7 | 8 | # platform specific settings for Windows/py2exe 9 | if sys.platform == "win32": 10 | import py2exe 11 | 12 | FREEZER = 'py2exe' 13 | FREEZER_OPTIONS = dict(compressed = 0, 14 | optimize = 0, 15 | bundle_files = 3, 16 | dll_excludes = ['MSVCP90.dll', 17 | 'mswsock.dll', 18 | 'powrprof.dll', 19 | 'USP10.dll',], 20 | ) 21 | exeICON = 'mondrian.ico' 22 | 23 | 24 | # platform specific settings for Mac/py2app 25 | elif sys.platform == "darwin": 26 | import py2app 27 | 28 | FREEZER = 'py2app' 29 | FREEZER_OPTIONS = dict(argv_emulation = False, 30 | iconfile = 'mondrian.icns', 31 | ) 32 | exeICON = None 33 | 34 | 35 | 36 | # Common settings 37 | NAME = "wxImageViewer" 38 | APP = [bdist_esky.Executable("image_viewer.py", 39 | gui_only=True, 40 | icon=exeICON, 41 | )] 42 | DATA_FILES = [ 'mondrian.ico' ] 43 | ESKY_OPTIONS = dict( freezer_module = FREEZER, 44 | freezer_options = FREEZER_OPTIONS, 45 | enable_appdata_dir = True, 46 | bundle_msvcrt = True, 47 | ) 48 | 49 | 50 | # Build the app and the esky bundle 51 | setup( name = NAME, 52 | scripts = APP, 53 | version = version.VERSION, 54 | data_files = DATA_FILES, 55 | options = dict(bdist_esky=ESKY_OPTIONS), 56 | ) -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.1/version.py: -------------------------------------------------------------------------------- 1 | VERSION='0.0.1' -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.2/mondrian.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_48_updating_your_app/Releases/image_viewer-0.0.2/mondrian.icns -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.2/mondrian.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_48_updating_your_app/Releases/image_viewer-0.0.2/mondrian.ico -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.2/setup.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | from esky import bdist_esky 3 | from setuptools import setup 4 | 5 | import version 6 | 7 | 8 | # platform specific settings for Windows/py2exe 9 | if sys.platform == "win32": 10 | import py2exe 11 | includes = ["wx.lib.pubsub.*", 12 | "wx.lib.pubsub.core.*", 13 | "wx.lib.pubsub.core.kwargs.*"] 14 | 15 | FREEZER = 'py2exe' 16 | FREEZER_OPTIONS = dict(compressed = 0, 17 | optimize = 0, 18 | bundle_files = 3, 19 | dll_excludes = ['MSVCP90.dll', 20 | 'mswsock.dll', 21 | 'powrprof.dll', 22 | 'USP10.dll',], 23 | includes = includes 24 | ) 25 | exeICON = 'mondrian.ico' 26 | 27 | 28 | # platform specific settings for Mac/py2app 29 | elif sys.platform == "darwin": 30 | import py2app 31 | 32 | FREEZER = 'py2app' 33 | FREEZER_OPTIONS = dict(argv_emulation = False, 34 | iconfile = 'mondrian.icns', 35 | ) 36 | exeICON = None 37 | 38 | 39 | 40 | # Common settings 41 | NAME = "wxImageViewer" 42 | APP = [bdist_esky.Executable("image_viewer.py", 43 | gui_only=True, 44 | icon=exeICON, 45 | )] 46 | DATA_FILES = [ 'mondrian.ico' ] 47 | 48 | ESKY_OPTIONS = dict( freezer_module = FREEZER, 49 | freezer_options = FREEZER_OPTIONS, 50 | enable_appdata_dir = True, 51 | bundle_msvcrt = True, 52 | ) 53 | 54 | 55 | # Build the app and the esky bundle 56 | setup( name = NAME, 57 | scripts = APP, 58 | version = version.VERSION, 59 | data_files = DATA_FILES, 60 | options = dict(bdist_esky=ESKY_OPTIONS) 61 | ) -------------------------------------------------------------------------------- /recipe_48_updating_your_app/Releases/image_viewer-0.0.2/version.py: -------------------------------------------------------------------------------- 1 | VERSION='0.0.2' -------------------------------------------------------------------------------- /recipe_49_xrc/login.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx import xrc 3 | 4 | class MyApp(wx.App): 5 | def OnInit(self): 6 | res = xrc.XmlResource("login.xrc") 7 | 8 | frame = res.LoadFrame(None, 'mainFrame') 9 | 10 | frame.Show() 11 | return True 12 | 13 | if __name__ == "__main__": 14 | app = MyApp(False) 15 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_49_xrc/login.xrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | wxVERTICAL 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | wxALL 19 | 5 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | wxALL 29 | 5 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | wxALL|wxALIGN_CENTRE 41 | 5 42 | 43 | 44 | 45 | 46 | 47 | wxALL|wxALIGN_CENTRE 48 | 5 49 | 50 | 2 51 | 3 52 | 4 53 | 2 54 | 55 | 5 56 | 57 | 58 | 9 | 10 | 11 | wxEXPAND 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /recipe_4_background_image/big_cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_4_background_image/big_cat.jpg -------------------------------------------------------------------------------- /recipe_4_background_image/daniweb_example.py: -------------------------------------------------------------------------------- 1 | # create a background image on a wxPython panel 2 | # and show a button on top of the image 3 | 4 | import wx 5 | 6 | class Panel1(wx.Panel): 7 | """class Panel1 creates a panel with an image on it, inherits wx.Panel""" 8 | def __init__(self, parent, id): 9 | # create the panel 10 | wx.Panel.__init__(self, parent, id) 11 | try: 12 | # pick an image file you have in the working 13 | # folder you can load .jpg .png .bmp or 14 | # .gif files 15 | image_file = 'big_cat.jpg' 16 | bmp1 = wx.Image( 17 | image_file, 18 | wx.BITMAP_TYPE_ANY).ConvertToBitmap() 19 | # image's upper left corner anchors at panel 20 | # coordinates (0, 0) 21 | self.bitmap1 = wx.StaticBitmap( 22 | self, -1, bmp1, (0, 0)) 23 | # show some image details 24 | str1 = "%s %dx%d" % (image_file, bmp1.GetWidth(), 25 | bmp1.GetHeight()) 26 | parent.SetTitle(str1) 27 | except IOError: 28 | print("Image file %s not found" % imageFile) 29 | raise SystemExit 30 | 31 | # button goes on the image --> self.bitmap1 is the 32 | # parent 33 | self.button1 = wx.Button( 34 | self.bitmap1, label='Button1', 35 | pos=(8, 8)) 36 | 37 | app = wx.App(False) 38 | 39 | # create a window/frame, no parent, -1 is default ID 40 | # change the size of the frame to fit the backgound images 41 | frame1 = wx.Frame(None, -1, "An image on a panel", 42 | size=(350, 400)) 43 | 44 | # create the class instance 45 | panel1 = Panel1(frame1, -1) 46 | frame1.Show(True) 47 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_4_background_image/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MainPanel(wx.Panel): 5 | """""" 6 | 7 | def __init__(self, parent): 8 | """Constructor""" 9 | wx.Panel.__init__(self, parent=parent) 10 | self.frame = parent 11 | 12 | sizer = wx.BoxSizer(wx.VERTICAL) 13 | hSizer = wx.BoxSizer(wx.HORIZONTAL) 14 | 15 | for num in range(4): 16 | label = "Button %s" % num 17 | btn = wx.Button(self, label=label) 18 | sizer.Add(btn, 0, wx.ALL, 5) 19 | hSizer.Add((1,1), 1, wx.EXPAND) 20 | hSizer.Add(sizer, 0, wx.TOP, 100) 21 | hSizer.Add((1,1), 0, wx.ALL, 75) 22 | self.SetSizer(hSizer) 23 | self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) 24 | 25 | def OnEraseBackground(self, evt): 26 | """ 27 | Add a picture to the background 28 | """ 29 | # yanked from ColourDB.py 30 | dc = evt.GetDC() 31 | 32 | if not dc: 33 | dc = wx.ClientDC(self) 34 | rect = self.GetUpdateRegion().GetBox() 35 | dc.SetClippingRect(rect) 36 | dc.Clear() 37 | bmp = wx.Bitmap("big_cat.jpg") 38 | dc.DrawBitmap(bmp, 0, 0) 39 | 40 | 41 | class MainFrame(wx.Frame): 42 | """""" 43 | 44 | def __init__(self): 45 | """Constructor""" 46 | wx.Frame.__init__(self, None, size=(600,450)) 47 | panel = MainPanel(self) 48 | self.Center() 49 | 50 | 51 | class Main(wx.App): 52 | """""" 53 | 54 | def __init__(self, redirect=False, filename=None): 55 | """Constructor""" 56 | wx.App.__init__(self, redirect, filename) 57 | dlg = MainFrame() 58 | dlg.Show() 59 | 60 | 61 | if __name__ == "__main__": 62 | app = Main() 63 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_50_xrc_grid/broken_grid.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx import xrc 3 | 4 | 5 | class MyApp(wx.App): 6 | def OnInit(self): 7 | self.res = xrc.XmlResource("grid.xrc") 8 | 9 | frame = self.res.LoadFrame(None, 'MyFrame') 10 | panel = xrc.XRCCTRL(frame, "MyPanel") 11 | grid = xrc.XRCCTRL(panel, "MyGrid") 12 | print(type(grid)) 13 | grid.CreateGrid(25, 6) 14 | 15 | sizer = wx.BoxSizer(wx.VERTICAL) 16 | sizer.Add(grid, 1, wx.EXPAND|wx.ALL, 5) 17 | 18 | panel.SetSizer(sizer) 19 | 20 | frame.Show() 21 | return True 22 | 23 | if __name__ == "__main__": 24 | app = MyApp(False) 25 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_50_xrc_grid/grid.xrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | XRC Grid 8 | 9 | -------------------------------------------------------------------------------- /recipe_50_xrc_grid/working_grid.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.grid 3 | from wx import xrc 4 | 5 | 6 | class MyApp(wx.App): 7 | def OnInit(self): 8 | self.res = xrc.XmlResource("grid.xrc") 9 | 10 | frame = self.res.LoadFrame(None, 'MyFrame') 11 | panel = xrc.XRCCTRL(frame, "MyPanel") 12 | grid = xrc.XRCCTRL(panel, "MyGrid") 13 | print(type(grid)) 14 | grid.CreateGrid(25, 6) 15 | 16 | sizer = wx.BoxSizer(wx.VERTICAL) 17 | sizer.Add(grid, 1, wx.EXPAND|wx.ALL, 5) 18 | 19 | panel.SetSizer(sizer) 20 | 21 | frame.Show() 22 | return True 23 | 24 | if __name__ == "__main__": 25 | app = MyApp(False) 26 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_51_xrced/first_app.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx import xrc 3 | 4 | class MyApp(wx.App): 5 | def OnInit(self): 6 | self.res = xrc.XmlResource("twoBtns.xrc") 7 | 8 | self.frame = self.res.LoadFrame(None, 'MainFrame') 9 | 10 | self.frame.Show() 11 | return True 12 | 13 | if __name__ == "__main__": 14 | app = MyApp(False) 15 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_51_xrced/notebook.xrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | wxVERTICAL 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | wxALL|wxEXPAND 20 | 5 21 | 22 | 23 | 24 | XRC Notebook Demo 25 | 26 | -------------------------------------------------------------------------------- /recipe_51_xrced/notebook_example.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx import xrc 3 | import wx.lib.platebtn as platebtn 4 | 5 | 6 | class MyApp(wx.App): 7 | def OnInit(self): 8 | self.res = xrc.XmlResource("notebook.xrc") 9 | 10 | frame = self.res.LoadFrame(None, 'DemoFrame') 11 | panel = xrc.XRCCTRL(frame, "DemoPanel") 12 | notebook = xrc.XRCCTRL(panel, "DemoNotebook") 13 | 14 | sizer = wx.BoxSizer(wx.VERTICAL) 15 | btn = platebtn.PlateButton(panel, label="Test", 16 | style=platebtn.PB_STYLE_DEFAULT) 17 | btn.Bind(wx.EVT_BUTTON, self.onButton) 18 | sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5) 19 | sizer.Add(btn) 20 | panel.SetSizer(sizer) 21 | 22 | frame.Show() 23 | return True 24 | 25 | 26 | def onButton(self, event): 27 | """""" 28 | print("You pressed the button!") 29 | 30 | 31 | if __name__ == "__main__": 32 | app = MyApp(False) 33 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_51_xrced/twoBtns.xrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | wxHORIZONTAL 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /recipe_51_xrced/twoBtns_xrc.py: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by pywxrc. 2 | # -*- coding: UTF-8 -*- 3 | 4 | import wx 5 | import wx.xrc as xrc 6 | 7 | __res = None 8 | 9 | def get_resources(): 10 | """ This function provides access to the XML resources in this module.""" 11 | global __res 12 | if __res == None: 13 | __init_resources() 14 | return __res 15 | 16 | 17 | 18 | 19 | class xrcMainFrame(wx.Frame): 20 | #!XRCED:begin-block:xrcMainFrame.PreCreate 21 | def PreCreate(self, pre): 22 | """ This function is called during the class's initialization. 23 | 24 | Override it for custom setup before the window is created usually to 25 | set additional window styles using SetWindowStyle() and SetExtraStyle(). 26 | """ 27 | pass 28 | 29 | #!XRCED:end-block:xrcMainFrame.PreCreate 30 | 31 | def __init__(self, parent): 32 | # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) 33 | pre = wx.PreFrame() 34 | self.PreCreate(pre) 35 | get_resources().LoadOnFrame(pre, parent, "MainFrame") 36 | self.PostCreate(pre) 37 | 38 | # Define variables for the controls, bind event handlers 39 | 40 | # ------------------------ Resource data ---------------------- 41 | 42 | def __init_resources(): 43 | global __res 44 | __res = xrc.EmptyXmlResource() 45 | 46 | __res.Load('twoBtns.xrc') 47 | -------------------------------------------------------------------------------- /recipe_51_xrced/twoBtns_xrc_subclass.py: -------------------------------------------------------------------------------- 1 | # twoBtns_xrc_subclass.py 2 | 3 | import twoBtns_xrc 4 | import wx 5 | 6 | 7 | class XrcFrameSubClass(twoBtns_xrc.xrcMainFrame): 8 | """""" 9 | 10 | def __init__(self): 11 | """Constructor""" 12 | twoBtns_xrc.xrcMainFrame.__init__(self, parent=None) 13 | self.Show() 14 | 15 | if __name__ == "__main__": 16 | app = wx.App(False) 17 | frame = XrcFrameSubClass() 18 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_52_centering_widgets/faux_spacers.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MainFrame(wx.Frame): 5 | """""" 6 | 7 | def __init__(self): 8 | """Constructor""" 9 | wx.Frame.__init__(self, None, title="Center the Button") 10 | panel = wx.Panel(self) 11 | 12 | h_sizer = wx.BoxSizer(wx.HORIZONTAL) 13 | main_sizer = wx.BoxSizer(wx.VERTICAL) 14 | 15 | btn = wx.Button(panel, label="Centered") 16 | h_sizer.Add(btn, 0, wx.CENTER) 17 | 18 | main_sizer.Add((0,0), 1, wx.EXPAND) 19 | main_sizer.Add(h_sizer, 0, wx.CENTER) 20 | main_sizer.Add((0,0), 1, wx.EXPAND) 21 | 22 | panel.SetSizer(main_sizer) 23 | 24 | self.Show() 25 | 26 | 27 | if __name__ == "__main__": 28 | app = wx.App(False) 29 | frame = MainFrame() 30 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_52_centering_widgets/nested_sizers.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MainFrame(wx.Frame): 4 | """""" 5 | 6 | 7 | def __init__(self): 8 | """Constructor""" 9 | wx.Frame.__init__(self, None, title="Center the Button") 10 | panel = wx.Panel(self) 11 | 12 | main_sizer = wx.BoxSizer(wx.VERTICAL) 13 | 14 | btn = wx.Button(panel, label="Centered") 15 | main_sizer.AddStretchSpacer() 16 | main_sizer.Add(btn, 0, wx.CENTER) 17 | main_sizer.AddStretchSpacer() 18 | 19 | panel.SetSizer(main_sizer) 20 | 21 | self.Show() 22 | 23 | 24 | if __name__ == "__main__": 25 | app = wx.App(False) 26 | frame = MainFrame() 27 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_52_centering_widgets/stretch_spacer.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | 4 | class MainFrame(wx.Frame): 5 | """""" 6 | 7 | 8 | def __init__(self): 9 | """Constructor""" 10 | wx.Frame.__init__(self, None, title="Center the Button") 11 | panel = wx.Panel(self) 12 | 13 | h_sizer = wx.BoxSizer(wx.HORIZONTAL) 14 | main_sizer = wx.BoxSizer(wx.VERTICAL) 15 | 16 | btn = wx.Button(panel, label="Centered") 17 | h_sizer.Add(btn, 0, wx.CENTER) 18 | 19 | main_sizer.AddStretchSpacer(prop=1) 20 | main_sizer.Add(h_sizer, 0, wx.CENTER) 21 | main_sizer.AddStretchSpacer(prop=1) 22 | 23 | panel.SetSizer(main_sizer) 24 | 25 | self.Show() 26 | 27 | 28 | if __name__ == "__main__": 29 | app = wx.App(False) 30 | frame = MainFrame() 31 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_53_widget_wrapping/main.py: -------------------------------------------------------------------------------- 1 | import random 2 | import wx 3 | from wx.lib.buttons import GenButton 4 | 5 | 6 | class MyPanel(wx.Panel): 7 | """""" 8 | 9 | def __init__(self, parent): 10 | """Constructor""" 11 | wx.Panel.__init__(self, parent) 12 | 13 | text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 14 | sizer = wx.WrapSizer() 15 | for letter in text: 16 | btn = GenButton(self, label=letter) 17 | r = random.randint(128, 255) 18 | g = random.randint(128, 255) 19 | b = random.randint(128, 255) 20 | btn.SetBackgroundColour(wx.Colour(r,g,b)) 21 | btn.Refresh() 22 | sizer.Add(btn, 0, wx.ALL, 5) 23 | 24 | self.SetSizer(sizer) 25 | 26 | 27 | class MyFrame(wx.Frame): 28 | """""" 29 | 30 | def __init__(self): 31 | """Constructor""" 32 | wx.Frame.__init__(self, None, title="WrapSizers", size=(400,500)) 33 | panel = MyPanel(self) 34 | self.Show() 35 | 36 | 37 | if __name__ == "__main__": 38 | app = wx.App(False) 39 | frame = MyFrame() 40 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_54_getting_selected_cells/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import wx.grid as gridlib 3 | 4 | 5 | class MyPanel(wx.Panel): 6 | """""" 7 | 8 | def __init__(self, parent): 9 | """Constructor""" 10 | wx.Panel.__init__(self, parent) 11 | self.currentlySelectedCell = (0, 0) 12 | 13 | self.myGrid = gridlib.Grid(self) 14 | self.myGrid.CreateGrid(12, 8) 15 | self.myGrid.Bind(gridlib.EVT_GRID_SELECT_CELL, self.onSingleSelect) 16 | self.myGrid.Bind(gridlib.EVT_GRID_RANGE_SELECT, self.onDragSelection) 17 | 18 | selectBtn = wx.Button(self, label="Get Selected Cells") 19 | selectBtn.Bind(wx.EVT_BUTTON, self.onGetSelection) 20 | 21 | sizer = wx.BoxSizer(wx.VERTICAL) 22 | sizer.Add(self.myGrid, 1, wx.EXPAND) 23 | sizer.Add(selectBtn, 0, wx.ALL|wx.CENTER, 5) 24 | self.SetSizer(sizer) 25 | 26 | def onDragSelection(self, event): 27 | """ 28 | Gets the cells that are selected by holding the left 29 | mouse button down and dragging 30 | """ 31 | if self.myGrid.GetSelectionBlockTopLeft(): 32 | top_left = self.myGrid.GetSelectionBlockTopLeft()[0] 33 | bottom_right = self.myGrid.GetSelectionBlockBottomRight()[0] 34 | self.printSelectedCells(top_left, bottom_right) 35 | 36 | def onGetSelection(self, event): 37 | """ 38 | Get whatever cells are currently selected 39 | """ 40 | cells = self.myGrid.GetSelectedCells() 41 | if not cells: 42 | if self.myGrid.GetSelectionBlockTopLeft(): 43 | top_left = self.myGrid.GetSelectionBlockTopLeft()[0] 44 | bottom_right = self.myGrid.GetSelectionBlockBottomRight()[0] 45 | self.printSelectedCells(top_left, bottom_right) 46 | else: 47 | print(self.currentlySelectedCell) 48 | else: 49 | print(cells) 50 | 51 | def onSingleSelect(self, event): 52 | """ 53 | Get the selection of a single cell by clicking or 54 | moving the selection with the arrow keys 55 | """ 56 | print("You selected Row %s, Col %s" % (event.GetRow(), 57 | event.GetCol())) 58 | self.currentlySelectedCell = (event.GetRow(), 59 | event.GetCol()) 60 | event.Skip() 61 | 62 | def printSelectedCells(self, top_left, bottom_right): 63 | """ 64 | Based on code from 65 | http://ginstrom.com/scribbles/2008/09/07/getting-the-selected-cells-from-a-wxpython-grid/ 66 | """ 67 | cells = [] 68 | 69 | rows_start = top_left[0] 70 | rows_end = bottom_right[0] 71 | 72 | cols_start = top_left[1] 73 | cols_end = bottom_right[1] 74 | 75 | rows = range(rows_start, rows_end+1) 76 | cols = range(cols_start, cols_end+1) 77 | 78 | cells.extend([(row, col) 79 | for row in rows 80 | for col in cols]) 81 | 82 | print("You selected the following cells: ", cells) 83 | 84 | for cell in cells: 85 | row, col = cell 86 | print(self.myGrid.GetCellValue(row, col)) 87 | 88 | 89 | class MyFrame(wx.Frame): 90 | """""" 91 | 92 | def __init__(self): 93 | """Constructor""" 94 | wx.Frame.__init__(self, parent=None, title="Single Cell Selection") 95 | panel = MyPanel(self) 96 | self.Show() 97 | 98 | 99 | if __name__ == "__main__": 100 | app = wx.App(False) 101 | frame = MyFrame() 102 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_5_resetting_background_color/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | 3 | class MyForm(wx.Frame): 4 | 5 | def __init__(self): 6 | wx.Frame.__init__(self, None, wx.ID_ANY, 7 | "Background Reset Tutorial") 8 | 9 | # Add a panel so it looks the correct on all platforms 10 | self.panel = wx.Panel(self, wx.ID_ANY) 11 | 12 | self.txt = wx.TextCtrl(self.panel) 13 | self.txt.SetBackgroundColour("Yellow") 14 | 15 | blueBtn = wx.Button(self.panel, 16 | label="Change Background Color") 17 | blueBtn.Bind(wx.EVT_BUTTON, self.onChangeBackground) 18 | resetBtn = wx.Button(self.panel, label="Reset") 19 | resetBtn.Bind(wx.EVT_BUTTON, self.onReset) 20 | 21 | topSizer = wx.BoxSizer(wx.VERTICAL) 22 | btnSizer = wx.BoxSizer(wx.HORIZONTAL) 23 | 24 | btnSizer.Add(blueBtn, 0, wx.ALL|wx.CENTER, 5) 25 | btnSizer.Add(resetBtn, 0, wx.ALL|wx.CENTER, 5) 26 | 27 | topSizer.Add(self.txt, 0, wx.ALL, 5) 28 | topSizer.Add(btnSizer, 0, wx.CENTER) 29 | self.panel.SetSizer(topSizer) 30 | 31 | def onChangeBackground(self, event): 32 | """ 33 | Change the background color of the panel 34 | """ 35 | self.panel.SetBackgroundColour("Blue") 36 | self.panel.Refresh() 37 | 38 | def onReset(self, event): 39 | """ 40 | Reset the color of the panel to the default color 41 | """ 42 | self.panel.SetBackgroundColour(wx.NullColour) 43 | self.txt.SetBackgroundColour(wx.NullColour) 44 | self.panel.Refresh() 45 | 46 | 47 | if __name__ == "__main__": 48 | app = wx.App(False) 49 | frame = MyForm() 50 | frame.Show() 51 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_6_dark_mode/__pycache__/dark_mode.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driscollis/wxpythoncookbookcode/aed9d14c4e51d54acc8b6a645fedf27896c44a6f/recipe_6_dark_mode/__pycache__/dark_mode.cpython-35.pyc -------------------------------------------------------------------------------- /recipe_6_dark_mode/dark_mode.py: -------------------------------------------------------------------------------- 1 | # dark_mode.py 2 | import wx 3 | 4 | try: 5 | from ObjectListView import ObjectListView 6 | except: 7 | ObjectListView = False 8 | 9 | 10 | def getWidgets(parent): 11 | """ 12 | Return a list of all the child widgets 13 | """ 14 | items = [parent] 15 | for item in parent.GetChildren(): 16 | items.append(item) 17 | if hasattr(item, "GetChildren"): 18 | for child in item.GetChildren(): 19 | items.append(child) 20 | return items 21 | 22 | 23 | def darkRowFormatter(listctrl, dark=False): 24 | """ 25 | Toggles the rows in a ListCtrl or ObjectListView widget. 26 | """ 27 | 28 | listItems = [listctrl.GetItem(i) for i 29 | in range(listctrl.GetItemCount())] 30 | for index, item in enumerate(listItems): 31 | if dark: 32 | if index % 2: 33 | item.SetBackgroundColour("Dark Grey") 34 | else: 35 | item.SetBackgroundColour("Light Grey") 36 | else: 37 | if index % 2: 38 | item.SetBackgroundColour("Light Blue") 39 | else: 40 | item.SetBackgroundColour("Yellow") 41 | listctrl.SetItem(item) 42 | 43 | 44 | def darkMode(self, normalPanelColor): 45 | """ 46 | Toggles dark mode 47 | """ 48 | widgets = getWidgets(self) 49 | panel = widgets[0] 50 | if normalPanelColor == panel.GetBackgroundColour(): 51 | dark_mode = True 52 | else: 53 | dark_mode = False 54 | for widget in widgets: 55 | if dark_mode: 56 | if isinstance(widget, ObjectListView) or isinstance(widget, wx.ListCtrl): 57 | darkRowFormatter(widget, dark=True) 58 | widget.SetBackgroundColour("Dark Grey") 59 | widget.SetForegroundColour("White") 60 | else: 61 | if isinstance(widget, ObjectListView) or isinstance(widget, wx.ListCtrl): 62 | darkRowFormatter(widget) 63 | widget.SetBackgroundColour("White") 64 | widget.SetForegroundColour("Black") 65 | continue 66 | widget.SetBackgroundColour(wx.NullColour) 67 | widget.SetForegroundColour("Black") 68 | self.Refresh() 69 | return dark_mode -------------------------------------------------------------------------------- /recipe_6_dark_mode/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | import dark_mode 3 | 4 | 5 | class MyPanel(wx.Panel): 6 | """""" 7 | 8 | def __init__(self, parent): 9 | """Constructor""" 10 | wx.Panel.__init__(self, parent) 11 | self.defaultColor = self.GetBackgroundColour() 12 | 13 | rows = [("Ford", "Taurus", "1996", "Blue"), 14 | ("Nissan", "370Z", "2010", "Green"), 15 | ("Porche", "911", "2009", "Red") 16 | ] 17 | self.list_ctrl = wx.ListCtrl(self, style=wx.LC_REPORT) 18 | 19 | self.list_ctrl.InsertColumn(0, "Make") 20 | self.list_ctrl.InsertColumn(1, "Model") 21 | self.list_ctrl.InsertColumn(2, "Year") 22 | self.list_ctrl.InsertColumn(3, "Color") 23 | 24 | index = 0 25 | for row in rows: 26 | self.list_ctrl.InsertStringItem(index, row[0]) 27 | self.list_ctrl.SetStringItem(index, 1, row[1]) 28 | self.list_ctrl.SetStringItem(index, 2, row[2]) 29 | self.list_ctrl.SetStringItem(index, 3, row[3]) 30 | if index % 2: 31 | self.list_ctrl.SetItemBackgroundColour(index, "white") 32 | else: 33 | self.list_ctrl.SetItemBackgroundColour(index, "yellow") 34 | index += 1 35 | 36 | btn = wx.ToggleButton(self, label="Toggle Dark") 37 | btn.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleDark) 38 | normalBtn = wx.Button(self, label="Test") 39 | 40 | sizer = wx.BoxSizer(wx.VERTICAL) 41 | sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5) 42 | sizer.Add(btn, 0, wx.ALL, 5) 43 | sizer.Add(normalBtn, 0, wx.ALL, 5) 44 | self.SetSizer(sizer) 45 | 46 | def onToggleDark(self, event): 47 | """""" 48 | dark_mode.darkMode(self, self.defaultColor) 49 | 50 | 51 | class MyFrame(wx.Frame): 52 | """""" 53 | 54 | def __init__(self): 55 | """Constructor""" 56 | wx.Frame.__init__(self, None, 57 | title="MvP ListCtrl Dark Mode Demo", 58 | size=(400, 400)) 59 | panel = MyPanel(self) 60 | self.Show() 61 | 62 | 63 | if __name__ == "__main__": 64 | app = wx.App(False) 65 | frame = MyFrame() 66 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_7_pubsub/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from wx.lib.pubsub import pub 3 | 4 | 5 | class OtherFrame(wx.Frame): 6 | """""" 7 | 8 | def __init__(self): 9 | """Constructor""" 10 | wx.Frame.__init__(self, None, wx.ID_ANY, "Secondary Frame") 11 | panel = wx.Panel(self) 12 | 13 | msg = "Enter a Message to send to the main frame" 14 | instructions = wx.StaticText(panel, label=msg) 15 | self.msgTxt = wx.TextCtrl(panel, value="") 16 | closeBtn = wx.Button(panel, label="Send and Close") 17 | closeBtn.Bind(wx.EVT_BUTTON, self.onSendAndClose) 18 | 19 | sizer = wx.BoxSizer(wx.VERTICAL) 20 | flags = wx.ALL|wx.CENTER 21 | sizer.Add(instructions, 0, flags, 5) 22 | sizer.Add(self.msgTxt, 0, flags, 5) 23 | sizer.Add(closeBtn, 0, flags, 5) 24 | panel.SetSizer(sizer) 25 | 26 | def onSendAndClose(self, event): 27 | """ 28 | Send a message and close frame 29 | """ 30 | msg = self.msgTxt.GetValue() 31 | pub.sendMessage("panelListener", message=msg) 32 | pub.sendMessage("panelListener", message="test2", arg2="2nd argument!") 33 | self.Close() 34 | 35 | 36 | class MyPanel(wx.Panel): 37 | """""" 38 | 39 | def __init__(self, parent): 40 | """Constructor""" 41 | wx.Panel.__init__(self, parent) 42 | pub.subscribe(self.myListener, "panelListener") 43 | 44 | btn = wx.Button(self, label="Open Frame") 45 | btn.Bind(wx.EVT_BUTTON, self.onOpenFrame) 46 | 47 | def myListener(self, message, arg2=None): 48 | """ 49 | Listener function 50 | """ 51 | print("Received the following message: " + message) 52 | if arg2: 53 | print("Received another arguments: " + str(arg2)) 54 | 55 | def onOpenFrame(self, event): 56 | """ 57 | Opens secondary frame 58 | """ 59 | frame = OtherFrame() 60 | frame.Show() 61 | 62 | 63 | class MyFrame(wx.Frame): 64 | """""" 65 | 66 | def __init__(self): 67 | """Constructor""" 68 | wx.Frame.__init__(self, None, title="New PubSub API Tutorial") 69 | panel = MyPanel(self) 70 | self.Show() 71 | 72 | 73 | if __name__ == "__main__": 74 | app = wx.App(False) 75 | frame = MyFrame() 76 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_8_pydispatcher/main.py: -------------------------------------------------------------------------------- 1 | import wx 2 | from pydispatch import dispatcher 3 | 4 | 5 | class OtherFrame(wx.Frame): 6 | """""" 7 | 8 | 9 | def __init__(self): 10 | """Constructor""" 11 | wx.Frame.__init__(self, None, wx.ID_ANY, "Secondary Frame") 12 | panel = wx.Panel(self) 13 | 14 | msg = "Enter a Message to send to the main frame" 15 | instructions = wx.StaticText(panel, label=msg) 16 | self.msgTxt = wx.TextCtrl(panel, value="") 17 | closeBtn = wx.Button(panel, label="Send and Close") 18 | closeBtn.Bind(wx.EVT_BUTTON, self.onSendAndClose) 19 | 20 | sizer = wx.BoxSizer(wx.VERTICAL) 21 | flags = wx.ALL|wx.CENTER 22 | sizer.Add(instructions, 0, flags, 5) 23 | sizer.Add(self.msgTxt, 0, flags, 5) 24 | sizer.Add(closeBtn, 0, flags, 5) 25 | panel.SetSizer(sizer) 26 | 27 | 28 | def onSendAndClose(self, event): 29 | """ 30 | Send a message and close frame 31 | """ 32 | msg = self.msgTxt.GetValue() 33 | dispatcher.send("panelListener", message=msg) 34 | dispatcher.send("panelListener", message="test2", arg2="2nd argument!") 35 | self.Close() 36 | 37 | 38 | class MyPanel(wx.Panel): 39 | """""" 40 | 41 | 42 | def __init__(self, parent): 43 | """Constructor""" 44 | wx.Panel.__init__(self, parent) 45 | 46 | dispatcher.connect(self.myListener, signal="panelListener", 47 | sender=dispatcher.Any) 48 | 49 | btn = wx.Button(self, label="Open Frame") 50 | btn.Bind(wx.EVT_BUTTON, self.onOpenFrame) 51 | 52 | 53 | def myListener(self, message, arg2=None): 54 | """ 55 | Listener function 56 | """ 57 | print("Received the following message: " + message) 58 | if arg2: 59 | print("Received another arguments: " + str(arg2)) 60 | 61 | 62 | def onOpenFrame(self, event): 63 | """ 64 | Opens secondary frame 65 | """ 66 | frame = OtherFrame() 67 | frame.Show() 68 | 69 | 70 | class MyFrame(wx.Frame): 71 | """""" 72 | 73 | 74 | def __init__(self): 75 | """Constructor""" 76 | wx.Frame.__init__(self, None, title="PyDispatcher Tutorial") 77 | panel = MyPanel(self) 78 | self.Show() 79 | 80 | 81 | if __name__ == "__main__": 82 | app = wx.App(False) 83 | frame = MyFrame() 84 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_9_disable_wizard_next/main_classic.py: -------------------------------------------------------------------------------- 1 | # wxPython Classic Edition 2 | 3 | import wx 4 | import wx.wizard 5 | 6 | 7 | class WizardPage(wx.wizard.PyWizardPage): 8 | 9 | def __init__(self, parent, title): 10 | wx.wizard.PyWizardPage.__init__(self, parent) 11 | self.next = None 12 | self.prev = None 13 | self.initializeUI(title) 14 | 15 | def initializeUI(self, title): 16 | # create grid layout manager 17 | self.sizer = wx.GridBagSizer() 18 | self.SetSizerAndFit(self.sizer) 19 | 20 | def addWidget(self, widget, pos, span): 21 | self.sizer.Add(widget, pos, span, wx.EXPAND) 22 | 23 | # getters and setters 24 | def SetPrev(self, prev): 25 | self.prev = prev 26 | 27 | def SetNext(self, next): 28 | self.next = next 29 | 30 | def GetPrev(self): 31 | return self.prev 32 | 33 | def GetNext(self): 34 | return self.next 35 | 36 | 37 | class MyWizard(wx.wizard.Wizard): 38 | """""" 39 | 40 | def __init__(self): 41 | """Constructor""" 42 | wx.wizard.Wizard.__init__(self, None, 43 | title="Disable Next") 44 | self.SetPageSize((500, 350)) 45 | 46 | mypage1 = self.create_page1() 47 | 48 | forward_btn = self.FindWindowById(wx.ID_FORWARD) 49 | forward_btn.Disable() 50 | 51 | self.timer = wx.Timer(self) 52 | self.Bind(wx.EVT_TIMER, self.onUpdate, self.timer) 53 | self.timer.Start(1) 54 | 55 | self.RunWizard(mypage1) 56 | 57 | def create_page1(self): 58 | page1 = WizardPage(self, "Page 1") 59 | d = wx.StaticText(page1, label="test") 60 | page1.addWidget(d, (2, 1), (1,5)) 61 | 62 | self.text1 = wx.TextCtrl(page1) 63 | page1.addWidget(self.text1, (3,1), (1,5)) 64 | 65 | self.text2 = wx.TextCtrl(page1) 66 | page1.addWidget(self.text2, (4,1), (1,5)) 67 | 68 | page2 = WizardPage(self, "Page 2") 69 | page2.SetName("page2") 70 | self.text3 = wx.TextCtrl(page2) 71 | self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.onPageChanged) 72 | page3 = WizardPage(self, "Page 3") 73 | 74 | # Set links 75 | page2.SetPrev(page1) 76 | page1.SetNext(page2) 77 | page3.SetPrev(page2) 78 | page2.SetNext(page3) 79 | 80 | return page1 81 | 82 | def onPageChanged(self, event): 83 | """""" 84 | page = event.GetPage() 85 | 86 | if page.GetName() == "page2": 87 | self.text3.SetValue(self.text2.GetValue()) 88 | 89 | def onUpdate(self, event): 90 | """ 91 | Enables the Next button if both text controls have values 92 | """ 93 | value_one = self.text1.GetValue() 94 | value_two = self.text2.GetValue() 95 | if value_one and value_two: 96 | forward_btn = self.FindWindowById(wx.ID_FORWARD) 97 | forward_btn.Enable() 98 | self.timer.Stop() 99 | 100 | 101 | def main(): 102 | """""" 103 | wizard = MyWizard() 104 | 105 | 106 | if __name__ == "__main__": 107 | app = wx.App(False) 108 | main() 109 | app.MainLoop() -------------------------------------------------------------------------------- /recipe_9_disable_wizard_next/main_phoenix.py: -------------------------------------------------------------------------------- 1 | # wxPython Phoenix Version 2 | 3 | import wx 4 | from wx.adv import Wizard, WizardPage 5 | 6 | class MyWizardPage(WizardPage): 7 | 8 | def __init__(self, parent, title): 9 | WizardPage.__init__(self, parent) 10 | self.next = None 11 | self.prev = None 12 | self.initializeUI(title) 13 | 14 | def initializeUI(self, title): 15 | # create grid layout manager 16 | self.sizer = wx.GridBagSizer() 17 | self.SetSizer(self.sizer) 18 | 19 | def addWidget(self, widget, pos, span): 20 | self.sizer.Add(widget, pos, span, wx.EXPAND) 21 | 22 | # getters and setters 23 | def SetPrev(self, prev): 24 | self.prev = prev 25 | 26 | def SetNext(self, next): 27 | self.next = next 28 | 29 | def GetPrev(self): 30 | return self.prev 31 | 32 | def GetNext(self): 33 | return self.next 34 | 35 | 36 | class MyWizard(Wizard): 37 | """""" 38 | 39 | def __init__(self): 40 | """Constructor""" 41 | Wizard.__init__(self, None, 42 | title="Disable Next") 43 | self.SetPageSize((500, 350)) 44 | 45 | mypage1 = self.create_page1() 46 | 47 | forward_btn = self.FindWindowById(wx.ID_FORWARD) 48 | forward_btn.Disable() 49 | 50 | self.timer = wx.Timer(self) 51 | self.Bind(wx.EVT_TIMER, self.onUpdate, self.timer) 52 | self.timer.Start(1) 53 | 54 | self.RunWizard(mypage1) 55 | 56 | def create_page1(self): 57 | page1 = MyWizardPage(self, "Page 1") 58 | d = wx.StaticText(page1, label="test") 59 | page1.addWidget(d, (2, 1), (1,5)) 60 | 61 | self.text1 = wx.TextCtrl(page1) 62 | page1.addWidget(self.text1, (3,1), (1,5)) 63 | 64 | self.text2 = wx.TextCtrl(page1) 65 | page1.addWidget(self.text2, (4,1), (1,5)) 66 | 67 | page2 = MyWizardPage(self, "Page 2") 68 | page2.SetName("page2") 69 | self.text3 = wx.TextCtrl(page2) 70 | self.Bind(wx.adv.EVT_WIZARD_PAGE_CHANGED, self.onPageChanged) 71 | 72 | page3 = MyWizardPage(self, "Page 3") 73 | 74 | # Set links 75 | page2.SetPrev(page1) 76 | page1.SetNext(page2) 77 | page3.SetPrev(page2) 78 | page2.SetNext(page3) 79 | 80 | return page1 81 | 82 | def onPageChanged(self, event): 83 | """""" 84 | page = event.GetPage() 85 | 86 | if page.GetName() == "page2": 87 | self.text3.SetValue(self.text2.GetValue()) 88 | 89 | def onUpdate(self, event): 90 | """ 91 | Enables the Next button if both text controls have values 92 | """ 93 | value_one = self.text1.GetValue() 94 | value_two = self.text2.GetValue() 95 | if value_one and value_two: 96 | forward_btn = self.FindWindowById(wx.ID_FORWARD) 97 | forward_btn.Enable() 98 | self.timer.Stop() 99 | 100 | 101 | def main(): 102 | """""" 103 | wizard = MyWizard() 104 | 105 | 106 | if __name__ == "__main__": 107 | app = wx.App(False) 108 | main() 109 | app.MainLoop() --------------------------------------------------------------------------------