#!/usr/bin/env python # coding: utf-8 # GUI Programming in Python # ============== # DesertPy 4/22/2015 # --------------------- # @ftlphys # Michael Gilbert # ### GUI programming is a mix of science and art... # ###A myriad of options... # * TCL/TK # - Comes with your python distribution # - Good for basic diaglogues and simple user interaction # * WxPython # - Built on WxWidgets written in C++ # - Feature rich and extensible # - Full 2.7 support, 3+ support in the works # # * QT # - PyQT: Feature rich, modern UI, QT5 support # - PySide: Feature rich, only QT4 support # * Kivy # - Built on OpenGL ES 2 in Cython # - Cross Platform to mobile and desktop # * ... # ###The Basics in Python # * Most GUI frameworks use OOP # * Class structures define objects like Windows, frames, dialogues, buttons, etc. # * These are all defined to run within a main GUI loop or event loop # ###Some tips for getting started... # * Documenation as always is your friend # * Stackoverflow and [WxPython Phoenix Doc site](http://wxpython.org/Phoenix/docs/html/index.html) # * Get a Good IDE! (Eclipse with Pydev, Sublime, Komodo, PyCharm, etc.) # * Make your life easier by starting from pre-existing examples or using things like [WxGlade](http://wxglade.sourceforge.net/) # * Try a mockup utility like the opensource Pencil or a real pencil. :-) # * Keep in mind that your code base will likely increase 2-10x in size # ###WxPython # * We start with a GUI main loop # * We usually begin by building a class that inherits from "Frame" # - Upon inheriting, we can set certain attributes such as size, title, etc. # * WxPython is designed to have attributes either set upon inheritance or edited later, but the design flow is strictly linear # # * We will divide things into 4 parts # - Define widgets (buttons, stat text, input text, checkbox, listctrl, etc.) # - Define properties & bindings # - Define layout # - Define methods # ###Boxes Boxes Everywhere... # *Note*: Everything in WxPython is contained within some sort of box sizer. # The benefit is that your layout and sizing are done relative to your content # ###Hello World! in WxPython # In[1]: import wx app = wx.App(False) # Create a new app, don't redirect stdout/stderr to a window. frame = wx.Frame(None, wx.ID_ANY, "Hello World") # A Frame is a top-level window. frame.Show(True) # Show the frame. app.MainLoop() # ### Let's Add a few things for the User to interact with... # In[ ]: import wx import datetime import math class HelloWorld(wx.Frame): def __init__(self, parent, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE | wx.SUNKEN_BORDER | wx.CLIP_CHILDREN): wx.Frame.__init__(self, parent, id, title, pos, size, style) diagnal=math.sqrt(3200**2+1800**2) display_res=wx.GetDisplaySize() self.multiplier=math.sqrt(display_res[0]**2+display_res[1]**2)/diagnal self.master_panel = wx.Panel(self, -1) self.hello_button = wx.Button(self.master_panel, -1 ,"Hello World") self.slider_label = wx.StaticText(self.master_panel, -1, "Select frequency of hellos") self.slider = wx.Slider(self.master_panel, -1, 25, 1, 100, size = (int(self.multiplier*250), -1), style = wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS ) self.hellos_to_send=25 self.__set_properties() self.__do_layout() def __set_properties(self): self.menu_bar = wx.MenuBar() self.help = wx.Menu() self.about_me = wx.MenuItem(self.help, wx.NewId(), "About...") self.help.AppendItem(self.about_me) self.menu_bar.Append(self.help, "Help") self.SetMenuBar(self.menu_bar) self.statusbar = self.CreateStatusBar() self.statusbar.SetStatusText(datetime.datetime.now(). strftime("%d %b %Y %H:%M:%S")) self.Bind(wx.EVT_MENU,self.about_program,self.about_me) self.Bind(wx.EVT_BUTTON, self.output_hellos, self.hello_button) self.Bind(wx.EVT_SCROLL_CHANGED, self.hello_count, self.slider) def __do_layout(self): self.panel_sizer = wx.BoxSizer(wx.VERTICAL) self.main_sizer = wx.BoxSizer(wx.VERTICAL) self.main_sizer.Add(self.hello_button, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, int(self.multiplier*10)) self.main_sizer.Add(self.slider_label, 0, wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_HORIZONTAL, int(self.multiplier*10)) self.main_sizer.Add(self.slider, 0, wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, int(self.multiplier*10)) self.master_panel.SetSizer(self.main_sizer) self.main_sizer.Fit(self.master_panel) self.panel_sizer.Add(self.master_panel, 1, wx.EXPAND) self.SetSizer(self.panel_sizer) self.panel_sizer.Fit(self) self.Layout() def about_program(self, evt): dlg = wx.MessageDialog(self, 'This program says hello to the world.', 'Greetings!', wx.OK | wx.ICON_INFORMATION ) dlg.ShowModal() dlg.Destroy() def hello_count(self, evt): self.hellos_to_send=int(evt.EventObject.GetValue()) def output_hellos(self, evt): for i in range(self.hellos_to_send): print(i+1, 'hello!') if __name__ == '__main__': app = wx.App() HelloWorldApp = HelloWorld(None, title = 'Hello World') HelloWorldApp.Show() app.MainLoop() # ### Kivy # * We have a main GUI loop just like WxPython # * We divide our code between python and KV lang # - This allows for separation of layout and logic # - MVC architecture (Model - View - Control) # * KV lang provides a pythonic domain specific language for GUI design # * We can deploy applications to Android and iOS # - This is made possible only under Linux (at the moment) using Buildozer # - Pyler: Generic Python API for all platforms (wraps Pyjnius & Pyobjus) # ###Hello World! in Kivy # In[4]: from kivy.app import App from kivy.uix.button import Button class TestApp(App): def build(self): return Button(text='Hello World') TestApp().run() # ###Hello World! in Kivy with kv lang # In[ ]: from kivy.app import App class TestApp(App): pass if __name__ == '__main__': TestApp().run() # In[ ]: Button: text: 'Hello from test.kv' # ###Kivy Resources # * [Creating Apps in Kivy by Dusty Phillips](http://shop.oreilly.com/product/0636920032595.do) # - [Code that accompanies the book including the Weather App](https://github.com/oreillymedia/creating_apps_in_kivy) # * [Kivy main site](http://kivy.org/#home) # * If on Linux, examples, including the gesture_board, are located /usr/share/kivy-examples # # ###General Tips & Tricks # * Use MVC whenever possible # * Avoid pixel declarations where possible and/or account for resolution on development platform # * Allow the GUI system to do all layouts in a relative fashion and fit to your content # # ###Questions? # #PyCon 2015 Montreal! # # ###Some Interesting Take aways... # * [coLaboratory](http://colaboratory.jupyter.org/welcome/) # * Type hints in Python 3.5 # * Microsoft kicking it up a notch in 3.5! # * [Keynote Catherine Bracy](https://www.youtube.com/watch?v=LOZk5ttyC9Y&feature=youtu.be) # * [Keynote Jacob Kaplan-Moss](https://www.youtube.com/watch?v=hIJdFxYlEKE&feature=youtu.be) #