############################################################################## # PyDemos2.pyw # Programming Python, 2nd Edition (PP2E), 1999--2001 # Version 2.0, 03/01: add source-code file viewer buttons. # # Launch major Python+Tk GUI examples from the book, in a # platform-neutral way. This file also serves as an index # to major program examples, though many book examples aren't # GUI-based, and so aren't listed here (e.g., see the Linux # gcc build scripts in the examples root directory for C # integration program pointers). Also see: # # - PyGadgets.py, a simpler script for starting programs in # non-demo mode that you wish to use on a regular basis # - PyGadgets_bar.pyw, which creates a button bar for starting # all PyGadgets programs on demand, not all at once # - Launcher.py for starting programs without environment # settings--finds Python, sets PYTHONPATH, etc. # - Launch_*.py for starting PyDemos and PyGadgets with # Launcher.py--run these for a quick look # - LaunchBrowser.py for running example web pages with an # automatically-located web browser # - README-PP2E.txt, for general examples information # # Internet-based demos live here: # http://starship.python.net/~lutz/PyInternetDemos.html # but this program tries to start a browser on the main web pages # automatically, either on the site above or on local page files. # Additional program comments were moved to file PyDemos.doc.txt ############################################################################## import sys, time, os, launchmodes from Tkinter import * # -live loads root pages off net, -file loads local files InternetMode = '-file' ################################## # start building main gui windows ################################## Root = Tk() Root.title('PP2E Demos 2.0') # build message window Stat = Toplevel() Stat.protocol('WM_DELETE_WINDOW', lambda:0) # ignore wm delete Stat.title('PP2E demo info') Info = Label(Stat, text = 'Select demo', font=('courier', 20, 'italic'), padx=12, pady=12, bg='lightblue') Info.pack(expand=YES, fill=BOTH) ############################################# # add launcher buttons with callback objects ############################################# from PP2E.Gui.TextEditor.textEditor import TextEditorMainPopup # demo launcher class class Launcher(launchmodes.PortableLauncher): # use wrapped launcher class def announce(self, text): # customize to set GUI label Info.config(text=text) def viewer(sources): for filename in sources: TextEditorMainPopup(Root, filename) # as popup in this process def demoButton(name, what, doit, code): rowfrm = Frame(Root) rowfrm.pack(side=TOP, expand=YES, fill=BOTH) b = Button(rowfrm, bg='navy', fg='white', relief=RIDGE, border=4) b.config(text=name, width=20, command=Launcher(what, doit)) b.pack(side=LEFT, expand=YES, fill=BOTH) b = Button(rowfrm, bg='beige', fg='navy') b.config(text='code', command=(lambda code=code: viewer(code))) b.pack(side=LEFT, fill=BOTH) demoButton(name='PyEdit', what='Text file editor', # edit myself doit='Gui/TextEditor/textEditor.pyw PyDemos2.pyw', # assume in cwd code=['Gui/TextEditor/textEditor.py']) # source viewer demoButton(name='PyView', what='Image slideshow, plus note editor', doit='Gui/SlideShow/slideShowPlus.py Gui/gifs', code=['Gui/SlideShow/slideShowPlus.py', 'Gui/SlideShow/slideShow.py']) demoButton(name='PyDraw', what='Draw and move graphics objects', doit='Gui/MovingPics/movingpics.py Gui/gifs', code=['Gui/MovingPics/movingpics.py']) demoButton(name='PyTree', what='Tree data structure viewer', doit='Dstruct/TreeView/treeview.py', code=['Dstruct/TreeView/treeview.py', 'Dstruct/TreeView/treeview_wrappers.py', 'Dstruct/Classics/btree.py', 'Lang/Parser/parser2.py']) demoButton(name='PyClock', what='Analog/digital clocks', doit='Gui/Clock/clockStyles.py Gui/gifs', code=['Gui/Clock/clockStyles.py', 'Gui/Clock/clock.py']) demoButton(name='PyToe', what='Tic-tac-toe game (AI)', doit='Ai/TicTacToe/tictactoe.py', code=['Ai/TicTacToe/tictactoe.py', 'Ai/TicTacToe/tictactoe_lists.py']) demoButton(name='PyForm', # view in-memory dict what='Persistent table viewer/editor', # or cwd shelve of class doit='Dbase/TableBrowser/formgui.py', # 0=do not reinit shelve #doit='Dbase/TableBrowser/formtable.py shelve 0 pyformData-1.5.2', #doit='Dbase/TableBrowser/formtable.py shelve 1 pyformData', code=['Dbase/TableBrowser/formgui.py', 'Dbase/TableBrowser/formtable.py']) demoButton(name='PyCalc', what='Calculator, plus extensions', doit='Lang/Calculator/calculator_plusplus.py', code=['Lang/Calculator/calculator_plusplus.py', 'Lang/Calculator/calculator_plus_ext.py', 'Lang/Calculator/calculator_plus_emb.py', 'Lang/Calculator/calculator.py']) demoButton(name='PyMail', what='Python+Tk pop/smtp email client', doit='Internet/Email/PyMailGui.py', code=['Internet/Email/PyMailGui.py', 'Internet/Email/pymail.py', 'Internet/Email/mailconfig.py']) demoButton(name='PyFtp', what='Python+Tk ftp clients', doit='Internet/Ftp/PyFtpGui.pyw', code=['Internet/Ftp/PyFtpGui.pyw', 'Internet/Ftp/getfilegui.py', 'Internet/Ftp/putfilegui.py', 'Internet/Ftp/getfile.py', 'Internet/Ftp/putfile.py', 'Internet/Sockets/form.py']) if InternetMode == '-file': pagepath = os.getcwd() + '/Internet/Cgi-Web' demoButton('PyErrata', 'Internet-based errata report system', 'LaunchBrowser.py -file %s/PyErrata/pyerrata.html' % pagepath, ['Internet/Cgi-Web/PyErrata/pyerrata.html']) demoButton('PyMailCgi', 'Browser-based pop/smtp email interface', 'LaunchBrowser.py -file %s/PyMailCgi/pymailcgi.html' % pagepath, ['Internet/Cgi-Web/PyMailCgi/pymailcgi.html']) demoButton('PyInternet', 'Internet-based demo launcher page', 'LaunchBrowser.py -file %s/PyInternetDemos.html' % pagepath, ['Internet/Cgi-Web/PyInternetDemos.html']) else: site = 'starship.python.net/~lutz' demoButton('PyErrata', 'Internet-based errata report system', 'LaunchBrowser.py -live PyErrata/pyerrata.html ' + site, ['Internet/Cgi-Web/PyErrata/pyerrata.html']) demoButton('PyMailCgi', 'Browser-based pop/smtp email interface', 'LaunchBrowser.py -live PyMailCgi/pymailcgi.html ' + site, ['Internet/Cgi-Web/PyMailCgi/pymailcgi.html']) demoButton('PyInternet', 'Main Internet demos launcher page', 'LaunchBrowser.py -live PyInternetDemos.html ' + site, ['Internet/Cgi-Web/PyInternetDemos.html']) #To try: bind mouse entry events to change info text when over a button #See also: site http://starship.python.net/~lutz/PyInternetDemos.html ############################################# # toggle info message box font once a second ############################################# def refreshMe(info, ncall): slant = ['normal', 'italic', 'bold', 'bold italic'][ncall % 4] info.config(font=('courier', 20, slant)) Root.after(1000, (lambda info=info, ncall=ncall: refreshMe(info, ncall+1)) ) ######################################## # unhide/hide status box on info clicks ######################################## Stat.iconify() def onInfo(): if Stat.state() == 'iconic': Stat.deiconify() else: Stat.iconify() # was 'normal' ############################################ # popup a few web link buttons if connected ############################################ radiovar = StringVar() # use a global def onLinks(): popup = Toplevel() popup.title('PP2E web site links') links = [("Book", 'LaunchBrowser.py -live about-pp.html rmi.net/~lutz'), ("Python", 'LaunchBrowser.py -live index.html www.python.org'), ("O'Reilly", 'LaunchBrowser.py -live index.html www.oreilly.com'), ("Author", 'LaunchBrowser.py -live index.html rmi.net/~lutz')] for (name, command) in links: callback = Launcher((name + "'s web site"), command) link = Radiobutton(popup, text=name, command=callback) link.config(relief=GROOVE, variable=radiovar, value=name) link.pack(side=LEFT, expand=YES, fill=BOTH) Button(popup, text='Quit', command=popup.destroy).pack(expand=YES,fill=BOTH) if InternetMode != '-live': from tkMessageBox import showwarning showwarning('PP2E Demos', 'Web links require an Internet connection') ############################################# # finish building main gui, start event loop ############################################# Button(Root, text='Info', command=onInfo).pack(side=TOP, fill=X) Button(Root, text='Links', command=onLinks).pack(side=TOP, fill=X) Button(Root, text='Quit', command=Root.quit).pack(side=BOTTOM, fill=X) refreshMe(Info, 0) # start toggling Root.mainloop()