summaryrefslogtreecommitdiffstats
path: root/Demo/tkinter
diff options
context:
space:
mode:
Diffstat (limited to 'Demo/tkinter')
-rwxr-xr-xDemo/tkinter/guido/MimeViewer.py143
-rwxr-xr-xDemo/tkinter/guido/dialog.py119
-rwxr-xr-xDemo/tkinter/guido/mbox.py288
-rwxr-xr-xDemo/tkinter/guido/rmt.py152
-rwxr-xr-xDemo/tkinter/guido/tst.py81
-rwxr-xr-xDemo/tkinter/guido/wish.py26
6 files changed, 809 insertions, 0 deletions
diff --git a/Demo/tkinter/guido/MimeViewer.py b/Demo/tkinter/guido/MimeViewer.py
new file mode 100755
index 0000000..5bf194a
--- /dev/null
+++ b/Demo/tkinter/guido/MimeViewer.py
@@ -0,0 +1,143 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# View a single MIME multipart message.
+# Display each part as a box.
+
+import string
+from types import *
+from Tkinter import *
+from ScrolledText import ScrolledText
+
+class MimeViewer:
+ def __init__(self, parent, title, msg):
+ self.title = title
+ self.msg = msg
+ self.frame = Frame(parent, {'relief': 'raised', 'bd': 2})
+ self.frame.packing = {'expand': 0, 'fill': 'both'}
+ self.button = Checkbutton(self.frame,
+ {'text': title,
+ 'command': self.toggle})
+ self.button.pack({'anchor': 'w'})
+ headertext = msg.getheadertext(
+ lambda x: x != 'received' and x[:5] != 'x400-')
+ height = countlines(headertext, 4)
+ if height:
+ self.htext = ScrolledText(self.frame,
+ {'height': height,
+ 'width': 80,
+ 'wrap': 'none',
+ 'relief': 'raised',
+ 'bd': 2})
+ self.htext.packing = {'expand': 1, 'fill': 'both',
+ 'after': self.button}
+ self.htext.insert('end', headertext)
+ else:
+ self.htext = Frame(self.frame,
+ {'relief': 'raised', 'bd': 2})
+ self.htext.packing = {'side': 'top',
+ 'ipady': 2,
+ 'fill': 'x',
+ 'after': self.button}
+ body = msg.getbody()
+ if type(body) == StringType:
+ self.pad = None
+ height = countlines(body, 10)
+ if height:
+ self.btext = ScrolledText(self.frame,
+ {'height': height,
+ 'width': 80,
+ 'wrap': 'none',
+ 'relief': 'raised',
+ 'bd': 2})
+ self.btext.packing = {'expand': 1,
+ 'fill': 'both'}
+ self.btext.insert('end', body)
+ else:
+ self.btext = None
+ self.parts = None
+ else:
+ self.pad = Frame(self.frame,
+ {'relief': 'flat', 'bd': 2})
+ self.pad.packing = {'side': 'left', 'ipadx': 10,
+ 'fill': 'y', 'after': self.htext}
+ self.parts = []
+ for i in range(len(body)):
+ p = MimeViewer(self.frame,
+ '%s.%d' % (title, i+1),
+ body[i])
+ self.parts.append(p)
+ self.btext = None
+ self.collapsed = 1
+ def pack(self):
+ self.frame.pack(self.frame.packing)
+ def destroy(self):
+ self.frame.destroy()
+ def show(self):
+ if self.collapsed:
+ self.button.invoke()
+ def toggle(self):
+ if self.collapsed:
+ self.explode()
+ else:
+ self.collapse()
+ def collapse(self):
+ self.collapsed = 1
+ for comp in self.htext, self.btext, self.pad:
+ if comp:
+ comp.forget()
+ if self.parts:
+ for part in self.parts:
+ part.frame.forget()
+ self.frame.pack({'expand': 0})
+ def explode(self):
+ self.collapsed = 0
+ for comp in self.htext, self.btext, self.pad:
+ if comp: comp.pack(comp.packing)
+ if self.parts:
+ for part in self.parts:
+ part.pack()
+ self.frame.pack({'expand': 1})
+
+def countlines(str, limit):
+ i = 0
+ n = 0
+ while n < limit:
+ i = string.find(str, '\n', i)
+ if i < 0: break
+ n = n+1
+ i = i+1
+ return n
+
+def main():
+ import sys
+ import getopt
+ import mhlib
+ opts, args = getopt.getopt(sys.argv[1:], '')
+ for o, a in opts:
+ pass
+ message = None
+ folder = 'inbox'
+ for arg in args:
+ if arg[:1] == '+':
+ folder = arg[1:]
+ else:
+ message = string.atoi(arg)
+
+ mh = mhlib.MH()
+ f = mh.openfolder(folder)
+ if not message:
+ message = f.getcurrent()
+ m = f.openmessage(message)
+
+ root = Tk()
+ tk = root.tk
+
+ top = MimeViewer(root, '+%s/%d' % (folder, message), m)
+ top.pack()
+ top.show()
+
+ root.minsize(1, 1)
+
+ tk.mainloop()
+
+if __name__ == '__main__': main()
diff --git a/Demo/tkinter/guido/dialog.py b/Demo/tkinter/guido/dialog.py
new file mode 100755
index 0000000..31f5340
--- /dev/null
+++ b/Demo/tkinter/guido/dialog.py
@@ -0,0 +1,119 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# A Python function that generates dialog boxes with a text message,
+# optional bitmap, and any number of buttons.
+# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
+
+from Tkinter import *
+
+def dialog(master, title, text, bitmap, default, *args):
+
+ # 1. Create the top-level window and divide it into top
+ # and bottom parts.
+
+ w = Toplevel(master, {'class': 'Dialog'})
+ w.tk.call('global', 'button')
+ w.title(title)
+ w.iconname('Dialog')
+
+ top = Frame(w, {'relief': 'raised', 'bd': 1,
+ Pack: {'side': 'top', 'fill': 'both'}})
+ bot = Frame(w, {'relief': 'raised', 'bd': 1,
+ Pack: {'side': 'bottom', 'fill': 'both'}})
+
+ # 2. Fill the top part with the bitmap and message.
+
+ msg = Message(top,
+ {'width': '3i',
+ 'text': text,
+ 'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
+ Pack: {'side': 'right', 'expand': 1,
+ 'fill': 'both',
+ 'padx': '3m', 'pady': '3m'}})
+ if bitmap:
+ bm = Label(top, {'bitmap': bitmap,
+ Pack: {'side': 'left',
+ 'padx': '3m', 'pady': '3m'}})
+
+ # 3. Create a row of buttons at the bottom of the dialog.
+
+ buttons = []
+ i = 0
+ for but in args:
+ b = Button(bot, {'text': but,
+ 'command': ('set', 'button', i)})
+ buttons.append(b)
+ if i == default:
+ bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
+ Pack: {'side': 'left', 'expand': 1,
+ 'padx': '3m', 'pady': '2m'}})
+ w.tk.call('raise', b)
+ b.pack ({'in': bd, 'side': 'left',
+ 'padx': '2m', 'pady': '2m',
+ 'ipadx': '2m', 'ipady': '1m'})
+ else:
+ b.pack ({'side': 'left', 'expand': 1,
+ 'padx': '3m', 'pady': '3m',
+ 'ipady': '2m', 'ipady': '1m'})
+ i = i+1
+
+ # 4. Set up a binding for <Return>, if there's a default,
+ # set a grab, and claim the focus too.
+
+ if default >= 0:
+ w.bind('<Return>',
+ lambda b=buttons[default], i=default:
+ (b.cmd('flash'),
+ b.tk.call('set', 'button', i)))
+
+ oldFocus = w.tk.call('focus')
+ w.tk.call('grab', 'set', w)
+ w.tk.call('focus', w)
+
+ # 5. Wait for the user to respond, then restore the focus
+ # and return the index of the selected button.
+
+ w.tk.call('tkwait', 'variable', 'button')
+ w.tk.call('destroy', w)
+ w.tk.call('focus', oldFocus)
+ return w.tk.call('set', 'button')
+
+# The rest is the test program.
+
+def go():
+ i = dialog(mainWidget,
+ 'Not Responding',
+ "The file server isn't responding right now; "
+ "I'll keep trying.",
+ '',
+ -1,
+ 'OK')
+ print 'pressed button', i
+ i = dialog(mainWidget,
+ 'File Modified',
+ 'File "tcl.h" has been modified since '
+ 'the last time it was saved. '
+ 'Do you want to save it before exiting the application?',
+ 'warning',
+ 0,
+ 'Save File',
+ 'Discard Changes',
+ 'Return To Editor')
+ print 'pressed button', i
+
+def test():
+ import sys
+ global mainWidget
+ mainWidget = Frame()
+ Pack.config(mainWidget)
+ start = Button(mainWidget,
+ {'text': 'Press Here To Start', 'command': go})
+ start.pack()
+ endit = Button(mainWidget,
+ {'text': 'Exit',
+ 'command': 'exit',
+ Pack: {'fill' : 'both'}})
+ mainWidget.tk.mainloop()
+
+if __name__ == '__main__':
+ test()
diff --git a/Demo/tkinter/guido/mbox.py b/Demo/tkinter/guido/mbox.py
new file mode 100755
index 0000000..a4e86da
--- /dev/null
+++ b/Demo/tkinter/guido/mbox.py
@@ -0,0 +1,288 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# Scan MH folder, display results in window
+
+import os
+import sys
+import regex
+import getopt
+import string
+import mhlib
+
+from Tkinter import *
+
+from dialog import dialog
+
+mailbox = os.environ['HOME'] + '/Mail'
+
+def main():
+ global root, tk, top, mid, bot
+ global folderbox, foldermenu, scanbox, scanmenu, viewer
+ global folder, seq
+ global mh, mhf
+
+ # Parse command line options
+
+ folder = 'inbox'
+ seq = 'all'
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], '')
+ except getopt.error, msg:
+ print msg
+ sys.exit(2)
+ for arg in args:
+ if arg[:1] == '+':
+ folder = arg[1:]
+ else:
+ seq = arg
+
+ # Initialize MH
+
+ mh = mhlib.MH()
+ mhf = mh.openfolder(folder)
+
+ # Build widget hierarchy
+
+ root = Tk()
+ tk = root.tk
+
+ top = Frame(root)
+ top.pack({'expand': 1, 'fill': 'both'})
+
+ # Build right part: folder list
+
+ right = Frame(top)
+ right.pack({'fill': 'y', 'side': 'right'})
+
+ folderbar = Scrollbar(right, {'relief': 'sunken', 'bd': 2})
+ folderbar.pack({'fill': 'y', 'side': 'right'})
+
+ folderbox = Listbox(right)
+ folderbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
+
+ foldermenu = Menu(root)
+ foldermenu.add('command',
+ {'label': 'Open Folder',
+ 'command': open_folder})
+ foldermenu.add('separator')
+ foldermenu.add('command',
+ {'label': 'Quit',
+ 'command': 'exit'})
+ foldermenu.bind('<ButtonRelease-3>', folder_unpost)
+
+ folderbox['yscrollcommand'] = (folderbar, 'set')
+ folderbar['command'] = (folderbox, 'yview')
+ folderbox.bind('<Double-1>', open_folder, 1)
+ folderbox.bind('<3>', folder_post)
+
+ # Build left part: scan list
+
+ left = Frame(top)
+ left.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
+
+ scanbar = Scrollbar(left, {'relief': 'sunken', 'bd': 2})
+ scanbar.pack({'fill': 'y', 'side': 'right'})
+
+ scanbox = Listbox(left, {'font': 'fixed'})
+ scanbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
+
+ scanmenu = Menu(root)
+ scanmenu.add('command',
+ {'label': 'Open Message',
+ 'command': open_message})
+ scanmenu.add('command',
+ {'label': 'Remove Message',
+ 'command': remove_message})
+ scanmenu.add('command',
+ {'label': 'Refile Message',
+ 'command': refile_message})
+ scanmenu.add('separator')
+ scanmenu.add('command',
+ {'label': 'Quit',
+ 'command': 'exit'})
+ scanmenu.bind('<ButtonRelease-3>', scan_unpost)
+
+ scanbox['yscrollcommand'] = (scanbar, 'set')
+ scanbar['command'] = (scanbox, 'yview')
+ scanbox.bind('<Double-1>', open_message)
+ scanbox.bind('<3>', scan_post)
+
+ # Separator between middle and bottom part
+
+ rule2 = Frame(root, {'bg': 'black'})
+ rule2.pack({'fill': 'x'})
+
+ # Build bottom part: current message
+
+ bot = Frame(root)
+ bot.pack({'expand': 1, 'fill': 'both'})
+ #
+ viewer = None
+
+ # Window manager commands
+
+ root.minsize(800, 1) # Make window resizable
+
+ # Fill folderbox with text
+
+ setfolders()
+
+ # Fill scanbox with text
+
+ rescan()
+
+ # Enter mainloop
+
+ root.mainloop()
+
+def folder_post(e):
+ x, y = e.x_root, e.y_root
+ foldermenu.post(x - 10, y - 10)
+ foldermenu.grab_set()
+
+def folder_unpost(e):
+ tk.call('update', 'idletasks')
+ foldermenu.grab_release()
+ foldermenu.unpost()
+ foldermenu.invoke('active')
+
+def scan_post(e):
+ x, y = e.x_root, e.y_root
+ scanmenu.post(x - 10, y - 10)
+ scanmenu.grab_set()
+
+def scan_unpost(e):
+ tk.call('update', 'idletasks')
+ scanmenu.grab_release()
+ scanmenu.unpost()
+ scanmenu.invoke('active')
+
+scanparser = regex.compile('^ *\([0-9]+\)')
+
+def open_folder(*e):
+ global folder, mhf
+ sel = folderbox.curselection()
+ if len(sel) != 1:
+ if len(sel) > 1:
+ msg = "Please open one folder at a time"
+ else:
+ msg = "Please select a folder to open"
+ dialog(root, "Can't Open Folder", msg, "", 0, "OK")
+ return
+ i = sel[0]
+ folder = folderbox.get(i)
+ mhf = mh.openfolder(folder)
+ rescan()
+
+def open_message(*e):
+ global viewer
+ sel = scanbox.curselection()
+ if len(sel) != 1:
+ if len(sel) > 1:
+ msg = "Please open one message at a time"
+ else:
+ msg = "Please select a message to open"
+ dialog(root, "Can't Open Message", msg, "", 0, "OK")
+ return
+ cursor = scanbox['cursor']
+ scanbox['cursor'] = 'watch'
+ tk.call('update', 'idletasks')
+ i = sel[0]
+ line = scanbox.get(i)
+ if scanparser.match(line) >= 0:
+ num = string.atoi(scanparser.group(1))
+ m = mhf.openmessage(num)
+ if viewer: viewer.destroy()
+ from MimeViewer import MimeViewer
+ viewer = MimeViewer(bot, '+%s/%d' % (folder, num), m)
+ viewer.pack()
+ viewer.show()
+ scanbox['cursor'] = cursor
+
+def interestingheader(header):
+ return header != 'received'
+
+def remove_message():
+ itop = scanbox.nearest(0)
+ sel = scanbox.curselection()
+ if not sel:
+ dialog(root, "No Message To Remove",
+ "Please select a message to remove", "", 0, "OK")
+ return
+ todo = []
+ for i in sel:
+ line = scanbox.get(i)
+ if scanparser.match(line) >= 0:
+ todo.append(string.atoi(scanparser.group(1)))
+ mhf.removemessages(todo)
+ rescan()
+ fixfocus(min(todo), itop)
+
+lastrefile = ''
+tofolder = None
+def refile_message():
+ global lastrefile, tofolder
+ itop = scanbox.nearest(0)
+ sel = scanbox.curselection()
+ if not sel:
+ dialog(root, "No Message To Refile",
+ "Please select a message to refile", "", 0, "OK")
+ return
+ foldersel = folderbox.curselection()
+ if len(foldersel) != 1:
+ if not foldersel:
+ msg = "Please select a folder to refile to"
+ else:
+ msg = "Please select exactly one folder to refile to"
+ dialog(root, "No Folder To Refile", msg, "", 0, "OK")
+ return
+ refileto = folderbox.get(foldersel[0])
+ todo = []
+ for i in sel:
+ line = scanbox.get(i)
+ if scanparser.match(line) >= 0:
+ todo.append(string.atoi(scanparser.group(1)))
+ print 'refile', todo, tofolder
+ if lastrefile != refileto or not tofolder:
+ print 'new folder'
+ lastrefile = refileto
+ tofolder = None
+ tofolder = mh.openfolder(lastrefile)
+ mhf.refilemessages(todo, tofolder)
+ rescan()
+ fixfocus(min(todo), itop)
+
+def fixfocus(near, itop):
+ n = scanbox.size()
+ for i in range(n):
+ line = scanbox.get(`i`)
+ if scanparser.match(line) >= 0:
+ num = string.atoi(scanparser.group(1))
+ if num >= near:
+ break
+ else:
+ i = 'end'
+ scanbox.select_from(i)
+ print 'yview', `itop`
+ scanbox.yview(itop)
+
+def setfolders():
+ folderbox.delete(0, 'end')
+ for fn in mh.listallfolders():
+ folderbox.insert('end', fn)
+
+def rescan():
+ global viewer
+ if viewer:
+ viewer.destroy()
+ viewer = None
+ scanbox.delete(0, 'end')
+ for line in scanfolder(folder, seq):
+ scanbox.insert('end', line)
+
+def scanfolder(folder = 'inbox', sequence = 'all'):
+ return map(
+ lambda line: line[:-1],
+ os.popen('scan +%s %s' % (folder, sequence), 'r').readlines())
+
+main()
diff --git a/Demo/tkinter/guido/rmt.py b/Demo/tkinter/guido/rmt.py
new file mode 100755
index 0000000..2ac2408
--- /dev/null
+++ b/Demo/tkinter/guido/rmt.py
@@ -0,0 +1,152 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# A Python program implementing rmt, an application for remotely
+# controlling other Tk applications.
+# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.5-8, pp. 273-276.
+
+# Note that because of forward references in the original, we
+# sometimes delay bindings until after the corresponding procedure is
+# defined. We also introduce names for some unnamed code blocks in
+# the original because of restrictions on lambda forms in Python.
+
+from Tkinter import *
+
+# 1. Create basic application structure: menu bar on top of
+# text widget, scrollbar on right.
+
+root = Tk()
+tk = root.tk
+mBar = Frame(root, {'relief': 'raised', 'bd': 2,
+ Pack: {'side': 'top', 'fill': 'x'}})
+f = Frame(root)
+f.pack({'expand': 1, 'fill': 'both'})
+s = Scrollbar(f, {'relief': 'flat',
+ Pack: {'side': 'right', 'fill': 'y'}})
+t = Text(f, {'relief': 'raised', 'bd': 2, 'yscrollcommand': (s, 'set'),
+ 'setgrid': 1,
+ Pack: {'side': 'left', 'fill': 'both', 'expand': 1}})
+
+t.tag_config('bold', {'font': '-Adobe-Courier-Bold-R-Normal-*-120-*'})
+s['command'] = (t, 'yview')
+root.title('Tk Remote Controller')
+root.iconname('Tk Remote')
+
+# 2. Create menu button and menus.
+
+file = Menubutton(mBar, {'text': 'File', 'underline': 0,
+ Pack: {'side': 'left'}})
+file_m = Menu(file)
+file['menu'] = file_m
+file_m_apps = Menu(file_m)
+file_m.add('cascade', {'label': 'Select Application', 'underline': 0,
+ 'menu': file_m_apps})
+file_m.add('command', {'label': 'Quit', 'underline': 0, 'command': 'exit'})
+
+# 3. Create bindings for text widget to allow commands to be
+# entered and information to be selected. New characters
+# can only be added at the end of the text (can't ever move
+# insertion point).
+
+def single1(e):
+ x = e.x
+ y = e.y
+ tk.setvar('tk_priv(selectMode)', 'char')
+ t.mark_set('anchor', At(x, y))
+ # Should focus W
+t.bind('<1>', single1)
+
+def double1(e):
+ x = e.x
+ y = e.y
+ tk.setvar('tk_priv(selectMode)', 'word')
+ tk.call('tk_textSelectTo', t, At(x, y))
+t.bind('<Double-1>', double1)
+
+def triple1(e):
+ x = e.x
+ y = e.y
+ tk.setvar('tk_priv(selectMode)', 'line')
+ tk.call('tk_textSelectTo', t, At(x, y))
+t.bind('<Triple-1>', triple1)
+
+def returnkey(e):
+ t.insert('insert', '\n')
+ invoke()
+t.bind('<Return>', returnkey)
+
+def controlv(e):
+ t.insert('insert', tk.call('selection', 'get'))
+ t.yview_pickplace('insert')
+ if t.index('insert')[-2:] == '.0':
+ invoke()
+t.bind('<Control-v>', controlv)
+
+# 4. Procedure to backspace over one character, as long as
+# the character isn't part of the prompt.
+
+def backspace(e):
+ if t.index('promptEnd') != t.index('insert - 1 char'):
+ t.delete('insert - 1 char', 'insert')
+ t.yview_pickplace('insert')
+t.bind('<BackSpace>', backspace)
+t.bind('<Control-h>', backspace)
+t.bind('<Delete>', backspace)
+
+
+# 5. Procedure that's invoked when return is typed: if
+# there's not yet a complete command (e.g. braces are open)
+# then do nothing. Otherwise, execute command (locally or
+# remotely), output the result or error message, and issue
+# a new prompt.
+
+def invoke():
+ cmd = t.get('promptEnd + 1 char', 'insert')
+ if tk.getboolean(tk.call('info', 'complete', cmd)):
+ if app == tk.call('winfo', 'name', '.'):
+ msg = tk.call('eval', cmd)
+ else:
+ msg = tk.call('send', app, cmd)
+ if msg:
+ t.insert('insert', msg + '\n')
+ prompt()
+ t.yview_pickplace('insert')
+
+def prompt():
+ t.insert('insert', app + ': ')
+ t.mark_set('promptEnd', 'insert - 1 char')
+ t.tag_add('bold', 'insert linestart', 'promptEnd')
+
+# 6. Procedure to select a new application. Also changes
+# the prompt on the current command line to reflect the new
+# name.
+
+def newApp(appName):
+ global app
+ app = appName
+ t.delete('promptEnd linestart', 'promptEnd')
+ t.insert('promptEnd', appName + ':')
+ t.tag_add('bold', 'promptEnd linestart', 'promptEnd')
+
+newApp_tcl = `id(newApp)`
+tk.createcommand(newApp_tcl, newApp)
+
+def fillAppsMenu():
+ file_m_apps.add('command')
+ file_m_apps.delete(0, 'last')
+ names = tk.splitlist(tk.call('winfo', 'interps'))
+ names = map(None, names) # convert tuple to list
+ names.sort()
+ for name in names:
+ file_m_apps.add('command', {'label': name,
+ 'command': (newApp_tcl, name)})
+
+file_m_apps['postcommand'] = fillAppsMenu
+mBar.tk_menuBar(file)
+
+# 7. Miscellaneous initialization.
+
+app = tk.call('winfo', 'name', '.')
+prompt()
+tk.call('focus', t)
+
+root.mainloop()
diff --git a/Demo/tkinter/guido/tst.py b/Demo/tkinter/guido/tst.py
new file mode 100755
index 0000000..ea573d2
--- /dev/null
+++ b/Demo/tkinter/guido/tst.py
@@ -0,0 +1,81 @@
+# tst.py
+from Tkinter import *
+import sys
+
+def do_hello():
+ print 'Hello world!'
+
+class Quit(Button):
+ def action(self):
+ self.quit()
+ def __init__(self, master=None, cnf={}):
+ Button.__init__(self, master,
+ {'text': 'Quit',
+ 'command': self.action})
+ Button.config(self, cnf)
+
+class Stuff(Canvas):
+ def enter(self, e):
+ print 'Enter'
+ self.itemconfig('current', {'fill': 'red'})
+ def leave(self, e):
+ print 'Leave'
+ self.itemconfig('current', {'fill': 'blue'})
+ def __init__(self, master=None, cnf={}):
+ Canvas.__init__(self, master,
+ {'width': 100, 'height': 100})
+ Canvas.config(self, cnf)
+ self.create_rectangle(30, 30, 70, 70,
+ {'fill': 'red', 'tags': 'box'})
+ Canvas.bind(self, 'box', '<Enter>', self.enter)
+ Canvas.bind(self, 'box', '<Leave>', self.leave)
+
+class Test(Frame):
+ text = 'Testing'
+ num = 1
+ def do_xy(self, e):
+ print (e.x, e.y)
+ def do_test(self):
+ if not self.num % 10:
+ self.text = 'Testing 1 ...'
+ self.text = self.text + ' ' + `self.num`
+ self.num = self.num + 1
+ self.testing['text'] = self.text
+ def do_err(self):
+ 1/0
+ def do_after(self):
+ self.testing.invoke()
+ self.after(10000, self.do_after)
+ def __init__(self, master=None):
+ Frame.__init__(self, master)
+ self['bd'] = 30
+ Pack.config(self)
+ self.bind('<Motion>', self.do_xy)
+ self.hello = Button(self, {'name': 'hello',
+ 'text': 'Hello',
+ 'command': do_hello,
+ Pack: {'fill': 'both'}})
+ self.testing = Button(self)
+ self.testing['text'] = self.text
+ self.testing['command'] = self.do_test
+ Pack.config(self.testing, {'fill': 'both'})
+ self.err = Button(self, {'text': 'Error',
+ 'command': self.do_err,
+ Pack: {'fill': 'both'}})
+ self.quit = Quit(self, {Pack: {'fill': 'both'}})
+ self.exit = Button(self,
+ {'text': 'Exit',
+ 'command': lambda: sys.exit(0),
+ Pack: {'fill': 'both'}})
+ self.stuff = Stuff(self, {Pack: {'padx': 2, 'pady': 2}})
+ self.do_after()
+
+test = Test()
+test.master.title('Tkinter Test')
+test.master.iconname('Test')
+test.master.maxsize(500, 500)
+test.testing.invoke()
+
+# Use the -i option and type ^C to get a prompt
+test.mainloop()
+
diff --git a/Demo/tkinter/guido/wish.py b/Demo/tkinter/guido/wish.py
new file mode 100755
index 0000000..16cacde
--- /dev/null
+++ b/Demo/tkinter/guido/wish.py
@@ -0,0 +1,26 @@
+# This is about all it requires to write a wish shell in Python!
+
+import tkinter
+
+tk = tkinter.create(':0', 'wish', 'Tk', 1)
+tk.call('update')
+
+cmd = ''
+
+while 1:
+ if cmd: prompt = ''
+ else: prompt = '% '
+ try:
+ line = raw_input(prompt)
+ except EOFError:
+ break
+ cmd = cmd + (line + '\n')
+ tk.record(line)
+ if tk.getboolean(tk.call('info', 'complete', cmd)):
+ try:
+ result = tk.call('eval', cmd)
+ except tkinter.TclError, msg:
+ print 'TclError:', msg
+ else:
+ if result: print result
+ cmd = ''