[
  {
    "path": "README.md",
    "content": "# TkDocs Examples\n\nThis repository contains example Tkinter code that appears in the book *Modern Tkinter* as well as the \ntutorial at https://tkdocs.com.\n"
  },
  {
    "path": "bindings.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nroot = Tk()\nl =ttk.Label(root, text=\"Starting...\")\nl.grid()\nl.bind('<Enter>', lambda e: l.configure(text='Moved mouse inside'))\nl.bind('<Leave>', lambda e: l.configure(text='Moved mouse outside'))\nl.bind('<1>', lambda e: l.configure(text='Clicked left mouse button'))\nl.bind('<Double-1>', lambda e: l.configure(text='Double clicked'))\nl.bind('<B3-Motion>', lambda e: l.configure(text=f'right button drag to {e.x},{e.y}'))\nroot.mainloop()\n"
  },
  {
    "path": "contextmenu.py",
    "content": "from tkinter import *\nroot = Tk()\nif (root.tk.call('tk', 'windowingsystem')=='aqua'):\n    root.event_add('<<ContextMenu>>', '<Control-Button-1>')\nmenu = Menu(root)\nfor i in ('One', 'Two', 'Three'):\n    menu.add_command(label=i)\nroot.bind('<<ContextMenu>>', lambda e: menu.post(e.x_root, e.y_root))\nroot.mainloop()\n"
  },
  {
    "path": "country.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nroot = Tk()\n\n# Initialize our country \"databases\":\n#  - the list of country codes (a subset anyway)\n#  - parallel list of country names, same order as the country codes\n#  - a hash table mapping country code to population\ncountrycodes = ('ar', 'au', 'be', 'br', 'ca', 'cn', 'dk', 'fi', 'fr', 'gr', 'in', 'it', 'jp', 'mx', 'nl', 'no', 'es', 'se', 'ch')\ncountrynames = ('Argentina', 'Australia', 'Belgium', 'Brazil', 'Canada', 'China', 'Denmark', \\\n        'Finland', 'France', 'Greece', 'India', 'Italy', 'Japan', 'Mexico', 'Netherlands', 'Norway', 'Spain', \\\n        'Sweden', 'Switzerland')\ncnames = StringVar(value=countrynames)\npopulations = {'ar':41000000, 'au':21179211, 'be':10584534, 'br':185971537, \\\n        'ca':33148682, 'cn':1323128240, 'dk':5457415, 'fi':5302000, 'fr':64102140, 'gr':11147000, \\\n        'in':1131043000, 'it':59206382, 'jp':127718000, 'mx':106535000, 'nl':16402414, \\\n        'no':4738085, 'es':45116894, 'se':9174082, 'ch':7508700}\n\n# Names of the gifts we can send\ngifts = { 'card':'Greeting card', 'flowers':'Flowers', 'nastygram':'Nastygram'}\n\n# State variables\ngift = StringVar()\nsentmsg = StringVar()\nstatusmsg = StringVar()\n\n# Called when the selection in the listbox changes; figure out\n# which country is currently selected, and then lookup its country\n# code, and from that, its population.  Update the status message\n# with the new population.  As well, clear the message about the\n# gift being sent, so it doesn't stick around after we start doing\n# other things.\ndef showPopulation(*args):\n    idxs = lbox.curselection()\n    if len(idxs)==1:\n        idx = int(idxs[0])\n        code = countrycodes[idx]\n        name = countrynames[idx]\n        popn = populations[code]\n        statusmsg.set(\"The population of %s (%s) is %d\" % (name, code, popn))\n    sentmsg.set('')\n\n# Called when the user double clicks an item in the listbox, presses\n# the \"Send Gift\" button, or presses the Return key.  In case the selected\n# item is scrolled out of view, make sure it is visible.\n#\n# Figure out which country is selected, which gift is selected with the \n# radiobuttons, \"send the gift\", and provide feedback that it was sent.\ndef sendGift(*args):\n    idxs = lbox.curselection()\n    if len(idxs)==1:\n        idx = int(idxs[0])\n        lbox.see(idx)\n        name = countrynames[idx]\n        # Gift sending left as an exercise to the reader\n        sentmsg.set(\"Sent %s to leader of %s\" % (gifts[gift.get()], name))\n\n# Create and grid the outer content frame\nc = ttk.Frame(root, padding=(5, 5, 12, 0))\nc.grid(column=0, row=0, sticky=(N,W,E,S))\nroot.grid_columnconfigure(0, weight=1)\nroot.grid_rowconfigure(0,weight=1)\n\n# Create the different widgets; note the variables that many\n# of them are bound to, as well as the button callback.\n# We're using the StringVar() 'cnames', constructed from 'countrynames'\nlbox = Listbox(c, listvariable=cnames, height=5)\nlbl = ttk.Label(c, text=\"Send to country's leader:\")\ng1 = ttk.Radiobutton(c, text=gifts['card'], variable=gift, value='card')\ng2 = ttk.Radiobutton(c, text=gifts['flowers'], variable=gift, value='flowers')\ng3 = ttk.Radiobutton(c, text=gifts['nastygram'], variable=gift, value='nastygram')\nsend = ttk.Button(c, text='Send Gift', command=sendGift, default='active')\nsentlbl = ttk.Label(c, textvariable=sentmsg, anchor='center')\nstatus = ttk.Label(c, textvariable=statusmsg, anchor=W)\n\n# Grid all the widgets\nlbox.grid(column=0, row=0, rowspan=6, sticky=(N,S,E,W))\nlbl.grid(column=1, row=0, padx=10, pady=5)\ng1.grid(column=1, row=1, sticky=W, padx=20)\ng2.grid(column=1, row=2, sticky=W, padx=20)\ng3.grid(column=1, row=3, sticky=W, padx=20)\nsend.grid(column=2, row=4, sticky=E)\nsentlbl.grid(column=1, row=5, columnspan=2, sticky=N, pady=5, padx=5)\nstatus.grid(column=0, row=6, columnspan=2, sticky=(W,E))\nc.grid_columnconfigure(0, weight=1)\nc.grid_rowconfigure(5, weight=1)\n\n# Set event bindings for when the selection in the listbox changes,\n# when the user double clicks the list, and when they hit the Return key\nlbox.bind('<<ListboxSelect>>', showPopulation)\nlbox.bind('<Double-1>', sendGift)\nroot.bind('<Return>', sendGift)\n\n# Colorize alternating lines of the listbox\nfor i in range(0,len(countrynames),2):\n    lbox.itemconfigure(i, background='#f0f0ff')\n\n# Set the starting state of the interface, including selecting the\n# default gift to send, and clearing the messages.  Select the first\n# country in the list; because the &lt;&lt;ListboxSelect&gt;&gt; event is only\n# fired when users makes a change, we explicitly call showPopulation.\ngift.set('card')\nsentmsg.set('')\nstatusmsg.set('')\nlbox.selection_set(0)\nshowPopulation()\n\nroot.mainloop()\n"
  },
  {
    "path": "dialog.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nroot = Tk()\n\nttk.Entry(root).grid()   # something to interact with\ndef dismiss ():\n    dlg.grab_release()\n    dlg.destroy()\n\ndlg = Toplevel(root)\nttk.Button(dlg, text=\"Done\", command=dismiss).grid()\ndlg.protocol(\"WM_DELETE_WINDOW\", dismiss) # intercept close button\ndlg.transient(root)   # dialog window is related to main\ndlg.wait_visibility() # can't grab until window appears, so we wait\ndlg.grab_set()        # ensure all input goes to our window\ndlg.wait_window()     # block until window is destroyed\n\nroot.mainloop()\n\n\n"
  },
  {
    "path": "f2m.py",
    "content": "from tkinter import *\r\nfrom tkinter import ttk\r\n\r\ndef calculate(*args):\r\n    try:\r\n        value = float(feet.get())\r\n        meters.set(round(0.3048 * value, 4))\r\n    except ValueError:\r\n        pass\r\n\r\nroot = Tk()\r\nroot.title(\"Feet to Meters\")\r\n\r\nmainframe = ttk.Frame(root, padding=(3, 3, 12, 12))\r\nmainframe.grid(column=0, row=0, sticky=(N, W, E, S))\r\n\r\nfeet = StringVar()\r\nfeet_entry = ttk.Entry(mainframe, width=7, textvariable=feet)\r\nfeet_entry.grid(column=2, row=1, sticky=(W, E))\r\n\r\nmeters = StringVar()\r\nttk.Label(mainframe, textvariable=meters).grid(column=2, row=2, sticky=(W, E))\r\n\r\nttk.Button(mainframe, text=\"Calculate\", command=calculate).grid(column=3, row=3, sticky=W)\r\n\r\nttk.Label(mainframe, text=\"feet\").grid(column=3, row=1, sticky=W)\r\nttk.Label(mainframe, text=\"is equivalent to\").grid(column=1, row=2, sticky=E)\r\nttk.Label(mainframe, text=\"meters\").grid(column=3, row=2, sticky=W)\r\n\r\nroot.columnconfigure(0, weight=1)\r\nroot.rowconfigure(0, weight=1)\r\nmainframe.columnconfigure(2, weight=1)\r\nfor child in mainframe.winfo_children(): \r\n    child.grid_configure(padx=5, pady=5)\r\n\r\nfeet_entry.focus()\r\nroot.bind(\"<Return>\", calculate)\r\n\r\nroot.mainloop()\r\n"
  },
  {
    "path": "f2mo.py",
    "content": "from tkinter import *\r\nfrom tkinter import ttk\r\n\r\nclass FeetToMeters:\r\n\r\n    def __init__(self, root):\r\n\r\n        root.title(\"Feet to Meters\")\r\n\r\n        mainframe = ttk.Frame(root, padding=(3, 3, 12, 12))\r\n        mainframe.grid(column=0, row=0, sticky=(N, W, E, S))\r\n       \r\n        self.feet = StringVar()\r\n        feet_entry = ttk.Entry(mainframe, width=7, textvariable=self.feet)\r\n        feet_entry.grid(column=2, row=1, sticky=(W, E))\r\n        self.meters = StringVar()\r\n\r\n        ttk.Label(mainframe, textvariable=self.meters).grid(column=2, row=2, sticky=(W, E))\r\n        ttk.Button(mainframe, text=\"Calculate\", command=self.calculate).grid(column=3, row=3, sticky=W)\r\n\r\n        ttk.Label(mainframe, text=\"feet\").grid(column=3, row=1, sticky=W)\r\n        ttk.Label(mainframe, text=\"is equivalent to\").grid(column=1, row=2, sticky=E)\r\n        ttk.Label(mainframe, text=\"meters\").grid(column=3, row=2, sticky=W)\r\n\r\n        root.columnconfigure(0, weight=1)\r\n        root.rowconfigure(0, weight=1)\r\n        mainframe.columnconfigure(2, weight=1)\r\n        for child in mainframe.winfo_children(): \r\n            child.grid_configure(padx=5, pady=5)\r\n\r\n        feet_entry.focus()\r\n        root.bind(\"<Return>\", self.calculate)\r\n        \r\n    def calculate(self, *args):\r\n        try:\r\n            value = float(self.feet.get())\r\n            self.meters.set(round(0.3048 * value, 4))\r\n        except ValueError:\r\n            pass\r\n\r\nroot = Tk()\r\nFeetToMeters(root)\r\nroot.mainloop()"
  },
  {
    "path": "gridexample1.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nroot = Tk()\n\ncontent = ttk.Frame(root)\nframe = ttk.Frame(content, borderwidth=5, relief=\"sunken\", width=200, height=100)\nnamelbl = ttk.Label(content, text=\"Name\")\nname = ttk.Entry(content)\n\nonevar = BooleanVar()\ntwovar = BooleanVar()\nthreevar = BooleanVar()\nonevar.set(True)\ntwovar.set(False)\nthreevar.set(True)\n\none = ttk.Checkbutton(content, text=\"One\", variable=onevar, onvalue=True)\ntwo = ttk.Checkbutton(content, text=\"Two\", variable=twovar, onvalue=True)\nthree = ttk.Checkbutton(content, text=\"Three\", variable=threevar, onvalue=True)\nok = ttk.Button(content, text=\"Okay\")\ncancel = ttk.Button(content, text=\"Cancel\")\n\ncontent.grid(column=0, row=0)\nframe.grid(column=0, row=0, columnspan=3, rowspan=2)\nnamelbl.grid(column=3, row=0, columnspan=2)\nname.grid(column=3, row=1, columnspan=2)\none.grid(column=0, row=5)\ntwo.grid(column=1, row=5)\nthree.grid(column=2, row=5)\nok.grid(column=3, row=5)\ncancel.grid(column=4, row=5)\n\nroot.mainloop()\n"
  },
  {
    "path": "gridexample2.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nroot = Tk()\n\ncontent = ttk.Frame(root, padding=(3,3,12,12))\nframe = ttk.Frame(content, borderwidth=5, relief=\"sunken\", width=200, height=100)\nnamelbl = ttk.Label(content, text=\"Name\")\nname = ttk.Entry(content)\n\nonevar = BooleanVar()\ntwovar = BooleanVar()\nthreevar = BooleanVar()\n\nonevar.set(True)\ntwovar.set(False)\nthreevar.set(True)\n\none = ttk.Checkbutton(content, text=\"One\", variable=onevar, onvalue=True)\ntwo = ttk.Checkbutton(content, text=\"Two\", variable=twovar, onvalue=True)\nthree = ttk.Checkbutton(content, text=\"Three\", variable=threevar, onvalue=True)\nok = ttk.Button(content, text=\"Okay\")\ncancel = ttk.Button(content, text=\"Cancel\")\n\ncontent.grid(column=0, row=0, sticky=(N, S, E, W))\nframe.grid(column=0, row=0, columnspan=3, rowspan=2, sticky=(N, S, E, W))\nnamelbl.grid(column=3, row=0, columnspan=2, sticky=(N, W), padx=5)\nname.grid(column=3, row=1, columnspan=2, sticky=(N, E, W), pady=5, padx=5)\none.grid(column=0, row=5)\ntwo.grid(column=1, row=5)\nthree.grid(column=2, row=5)\nok.grid(column=3, row=5)\ncancel.grid(column=4, row=5)\n\nroot.columnconfigure(0, weight=1)\nroot.rowconfigure(0, weight=1)\ncontent.columnconfigure(0, weight=3)\ncontent.columnconfigure(1, weight=3)\ncontent.columnconfigure(2, weight=3)\ncontent.columnconfigure(3, weight=1)\ncontent.columnconfigure(4, weight=1)\ncontent.rowconfigure(1, weight=1)\n\nroot.mainloop()\n"
  },
  {
    "path": "hello.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nroot = Tk()\nttk.Button(root, text=\"Hello World\").grid()\nroot.mainloop()\n"
  },
  {
    "path": "logwindow.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nfrom datetime import datetime\n\nroot = Tk()\nlog = Text(root, state='disabled', width=80, height=24, wrap='none')\nlog.grid()\n\ndef writeToLog(msg):\n    numlines = int(log.index('end - 1 line').split('.')[0])\n    log['state'] = 'normal'\n    if numlines == 24:\n        log.delete(1.0, 2.0)\n    if log.index('end-1c')!='1.0':\n        log.insert('end', '\\n')\n    log.insert('end', msg)\n    log['state'] = 'disabled'\n\n\ndef writemsg():\n    writeToLog(str(datetime.now())+\": all is well\")\n    root.after(200, writemsg)\n    \nroot.after(200, writemsg)\n\nroot.mainloop()\n"
  },
  {
    "path": "longrunning.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nroot = Tk()\n\ndef start():\n    b.configure(text='Stop', command=stop)\n    l['text'] = 'Working...'\n    global interrupt; interrupt = False\n    root.after(1, step)\n    \ndef stop():\n    global interrupt; interrupt = True\n    \ndef step(count=0):\n    p['value'] = count\n    if interrupt:\n        result(None)\n        return\n    root.after(100)  # next step in our operation; don't take too long!\n    if count == 20: # done!\n        result(42)\n        return\n    root.after(1, lambda: step(count+1))\n    \ndef result(answer):\n    p['value'] = 0\n    b.configure(text='Start', command=start)\n    l['text'] = \"Answer: \" + str(answer) if answer else \"No Answer\"\n    \nf = ttk.Frame(root); f.grid()\nb = ttk.Button(f, text=\"Start!\", command=start); b.grid(column=1, row=0, padx=5, pady=5)\nl = ttk.Label(f, text=\"No Answer\"); l.grid(column=0, row=0, padx=5, pady=5)\np = ttk.Progressbar(f, orient=\"horizontal\", mode=\"determinate\", maximum=20); \np.grid(column=0, row=1, padx=5, pady=5)\n\nroot.mainloop()\n\n\n"
  },
  {
    "path": "menu.py",
    "content": "from tkinter import *\nfrom tkinter import ttk, messagebox\n\nroot = Tk()\nttk.Entry(root).grid()\nm = Menu(root)\nm_edit = Menu(m)\nm.add_cascade(menu=m_edit, label=\"Edit\")\nm_edit.add_command(label=\"Paste\", command=lambda: root.focus_get().event_generate(\"<<Paste>>\"))\nm_edit.add_command(label=\"Find...\", command=lambda: root.event_generate(\"<<OpenFindDialog>>\"))\nroot['menu'] = m\n\ndef launchFindDialog(*args):\n    messagebox.showinfo(message=\"I hope you find what you're looking for!\")\n    \nroot.bind(\"<<OpenFindDialog>>\", launchFindDialog)\nroot.mainloop()\n"
  },
  {
    "path": "numvalidate.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nroot=Tk()\n\nimport re\ndef check_num(newval):\n    return re.match('^[0-9]*$', newval) is not None and len(newval) <= 5\ncheck_num_wrapper = (root.register(check_num), '%P')\n\nnum = StringVar()\ne = ttk.Entry(root, textvariable=num, validate='key', validatecommand=check_num_wrapper)\ne.grid(column=0, row=0, sticky='we')\n\nroot.mainloop()\n\n\n"
  },
  {
    "path": "recentfiles.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nimport glob\nimport os\nimport os.path\nroot=Tk()\n\ndef openFile(f):\n    print(f)\n\nrecent_files = glob.glob(os.getcwd()+'/*.py')\nmenubar = Menu(root)\nroot['menu'] = menubar\nmenu_file = Menu(menubar)\nmenu_edit = Menu(menubar)\nmenubar.add_cascade(menu=menu_file, label='File')\nmenubar.add_cascade(menu=menu_edit, label='Edit')\nmenu_recent = Menu(menu_file)\nmenu_file.add_cascade(menu=menu_recent, label='Open Recent')\nfor f in recent_files:\n    menu_recent.add_command(label=os.path.basename(f), command=lambda: openFile(f))\n\nroot.mainloop()\n\n\n"
  },
  {
    "path": "scale.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nroot=Tk()\n\n# label tied to the same variable as the scale, so auto-updates\nnum = StringVar()\nttk.Label(root, textvariable=num).grid(column=0, row=0, sticky='we')\n\n# label that we'll manually update via the scale's command callback\nmanual = ttk.Label(root)\nmanual.grid(column=0, row=1, sticky='we')\n\ndef update_lbl(val):\n   manual['text'] = \"Scale at \" + val\n\nscale = ttk.Scale(root, orient='horizontal', length=200, from_=1.0, to=100.0, variable=num, command=update_lbl)\nscale.grid(column=0, row=2, sticky='we')\nscale.set(20)\n\nroot.mainloop()\n\n\n"
  },
  {
    "path": "scrollbar.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nroot = Tk()\nl = Listbox(root, height=5)\nl.grid(column=0, row=0, sticky=(N,W,E,S))\ns = ttk.Scrollbar(root, orient=VERTICAL, command=l.yview)\ns.grid(column=1, row=0, sticky=(N,S))\nl['yscrollcommand'] = s.set\nttk.Label(root, text=\"Status message here\", anchor=(W)).grid(column=0, columnspan=2, row=1, sticky=(W,E))\nroot.grid_columnconfigure(0, weight=1)\nroot.grid_rowconfigure(0, weight=1)\nfor i in range(1,101):\n    l.insert('end', 'Line %d of 100' % i)\nroot.mainloop()\n"
  },
  {
    "path": "scrolledtext.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nroot=Tk()\n\nt = Text(root, width = 40, height = 5, wrap = \"none\")\nys = ttk.Scrollbar(root, orient = 'vertical', command = t.yview)\nxs = ttk.Scrollbar(root, orient = 'horizontal', command = t.xview)\nt['yscrollcommand'] = ys.set\nt['xscrollcommand'] = xs.set\nt.insert('end', \"Lorem ipsum...\\n...\\n... dolor sit amet, consectetur adipiscing elit. Cras tincidunt tortor sit amet pretium semper. Pellentesque ac laoreet nulla. Fusce quis sapien ut magna ornare lacinia condimentum vel dui. Pellentesque volutpat pulvinar facilisis. Nunc lacus justo, imperdiet a urna at, condimentum gravida erat. \\nAliquam ornare mi id dui blandit laoreet. Donec sed \\nelit pretium arcu elementum lobortis ac at est. Curabitur nec \\nsapien quam. Duis sit amet lectus quis odio finibus viverra. Duis dapibus dui a tempus mollis. Vestibulum porta sem id tristique maximus. Fusce molestie purus ligula, eu auctor mi egestas quis.\")\nt.grid(column = 0, row = 0, sticky = 'nwes')\nxs.grid(column = 0, row = 1, sticky = 'we')\nys.grid(column = 1, row = 0, sticky = 'ns')\nroot.grid_columnconfigure(0, weight = 1)\nroot.grid_rowconfigure(0, weight = 1)\n\nroot.mainloop()\n"
  },
  {
    "path": "sketch1.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nlastx, lasty = 0, 0\n\ndef xy(event):\n    global lastx, lasty\n    lastx, lasty = event.x, event.y\n\ndef addLine(event):\n    global lastx, lasty\n    canvas.create_line(lastx, lasty, event.x, event.y)\n    lastx, lasty = event.x, event.y\n\nroot = Tk()\nroot.columnconfigure(0, weight=1)\nroot.rowconfigure(0, weight=1)\n\ncanvas = Canvas(root)\ncanvas.grid(column=0, row=0, sticky=(N, W, E, S))\ncanvas.bind(\"<Button-1>\", xy)\ncanvas.bind(\"<B1-Motion>\", addLine)\n\nroot.mainloop()\n"
  },
  {
    "path": "sketch2.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nlastx, lasty = 0, 0\ncolor = \"black\"\n\ndef xy(event):\n    global lastx, lasty\n    lastx, lasty = event.x, event.y\n\ndef setColor(newcolor):\n    global color\n    color = newcolor\n\ndef addLine(event):\n    global lastx, lasty\n    canvas.create_line(lastx, lasty, event.x, event.y, fill=color)\n    lastx, lasty = event.x, event.y\n\nroot = Tk()\nroot.columnconfigure(0, weight=1)\nroot.rowconfigure(0, weight=1)\n\ncanvas = Canvas(root)\ncanvas.grid(column=0, row=0, sticky=(N, W, E, S))\ncanvas.bind(\"<Button-1>\", xy)\ncanvas.bind(\"<B1-Motion>\", addLine)\n\nid = canvas.create_rectangle(10, 10, 30, 30, fill=\"red\")\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"red\"))\nid = canvas.create_rectangle(10, 35, 30, 55, fill=\"blue\")\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"blue\"))\nid = canvas.create_rectangle(10, 60, 30, 80, fill=\"black\")\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"black\"))\t\n\nroot.mainloop()\n"
  },
  {
    "path": "sketch3.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nlastx, lasty = 0, 0\ncolor = \"black\"\n\ndef xy(event):\n    global lastx, lasty\n    lastx, lasty = event.x, event.y\n\ndef setColor(newcolor):\n    global color\n    color = newcolor\n    canvas.dtag('all', 'paletteSelected')\n    canvas.itemconfigure('palette', outline='white')\n    canvas.addtag('paletteSelected', 'withtag', 'palette%s' % color)\n    canvas.itemconfigure('paletteSelected', outline='#999999')\n\ndef addLine(event):\n    global lastx, lasty\n    canvas.create_line(lastx, lasty, event.x, event.y, fill=color, width=5, tags='currentline')\n    lastx, lasty = event.x, event.y\n\ndef doneStroke(event):\n    canvas.itemconfigure('currentline', width=1)        \n\nroot = Tk()\nroot.columnconfigure(0, weight=1)\nroot.rowconfigure(0, weight=1)\n\ncanvas = Canvas(root)\ncanvas.grid(column=0, row=0, sticky=(N, W, E, S))\ncanvas.bind(\"<Button-1>\", xy)\ncanvas.bind(\"<B1-Motion>\", addLine)\ncanvas.bind(\"<B1-ButtonRelease>\", doneStroke)\n\nid = canvas.create_rectangle(10, 10, 30, 30, fill=\"red\", tags=('palette', 'palettered'))\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"red\"))\nid = canvas.create_rectangle(10, 35, 30, 55, fill=\"blue\", tags=('palette', 'paletteblue'))\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"blue\"))\nid = canvas.create_rectangle(10, 60, 30, 80, fill=\"black\", tags=('palette', 'paletteblack', 'paletteSelected'))\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"black\"))\t\n\nroot.mainloop()\n"
  },
  {
    "path": "sketch4.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nroot = Tk()\n\nh = ttk.Scrollbar(root, orient=HORIZONTAL)\nv = ttk.Scrollbar(root, orient=VERTICAL)\ncanvas = Canvas(root, scrollregion=(0, 0, 1000, 1000), yscrollcommand=v.set, xscrollcommand=h.set)\nh['command'] = canvas.xview\nv['command'] = canvas.yview\n\ncanvas.grid(column=0, row=0, sticky=(N,W,E,S))\nh.grid(column=0, row=1, sticky=(W,E))\nv.grid(column=1, row=0, sticky=(N,S))\nroot.grid_columnconfigure(0, weight=1)\nroot.grid_rowconfigure(0, weight=1)\n\nlastx, lasty = 0, 0\n\ndef xy(event):\n    global lastx, lasty\n    lastx, lasty = canvas.canvasx(event.x), canvas.canvasy(event.y)\n\ndef setColor(newcolor):\n    global color\n    color = newcolor\n    canvas.dtag('all', 'paletteSelected')\n    canvas.itemconfigure('palette', outline='white')\n    canvas.addtag('paletteSelected', 'withtag', 'palette%s' % color)\n    canvas.itemconfigure('paletteSelected', outline='#999999')\n\ndef addLine(event):\n    global lastx, lasty\n    x, y = canvas.canvasx(event.x), canvas.canvasy(event.y)\n    canvas.create_line(lastx, lasty, x, y, fill=color, width=5, tags='currentline')\n    lastx, lasty = x, y\n\ndef doneStroke(event):\n    canvas.itemconfigure('currentline', width=1)        \n        \ncanvas.bind(\"<Button-1>\", xy)\ncanvas.bind(\"<B1-Motion>\", addLine)\ncanvas.bind(\"<B1-ButtonRelease>\", doneStroke)\n\nid = canvas.create_rectangle(10, 10, 30, 30, fill=\"red\", tags=('palette', 'palettered'))\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"red\"))\nid = canvas.create_rectangle(10, 35, 30, 55, fill=\"blue\", tags=('palette', 'paletteblue'))\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"blue\"))\nid = canvas.create_rectangle(10, 60, 30, 80, fill=\"black\", tags=('palette', 'paletteblack', 'paletteSelected'))\ncanvas.tag_bind(id, \"<Button-1>\", lambda x: setColor(\"black\"))\n\nsetColor('black')\ncanvas.itemconfigure('palette', width=5)\nroot.mainloop()\n"
  },
  {
    "path": "sketcho.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nclass Sketchpad(Canvas):\n    def __init__(self, parent, **kwargs):\n        super().__init__(parent, **kwargs)\n        self.bind(\"<Button-1>\", self.save_posn)\n        self.bind(\"<B1-Motion>\", self.add_line)\n        \n    def save_posn(self, event):\n        self.lastx, self.lasty = event.x, event.y\n\n    def add_line(self, event):\n        self.create_line(self.lastx, self.lasty, event.x, event.y)\n        self.save_posn(event)\n\nroot = Tk()\nroot.columnconfigure(0, weight=1)\nroot.rowconfigure(0, weight=1)\n\nsketch = Sketchpad(root)\nsketch.grid(column=0, row=0, sticky=(N, W, E, S))\n\nroot.mainloop()\n"
  },
  {
    "path": "stackorder.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\nroot = Tk()\nlittle = ttk.Label(root, text=\"Little\")\nbigger = ttk.Label(root, text='Much bigger label')\nlittle.grid(column=0,row=0)\nbigger.grid(column=0,row=0)\nroot.after(2000, lambda: little.lift())\nroot.mainloop()\n"
  },
  {
    "path": "validate.py",
    "content": "from tkinter import *\nfrom tkinter import ttk\n\nroot=Tk()\n\nimport re\nerrmsg = StringVar()\nformatmsg = \"Zip should be ##### or #####-####\"\n\ndef check_zip(newval, op):\n    errmsg.set('')\n    valid = re.match('^[0-9]{5}(\\-[0-9]{4})?$', newval) is not None\n    btn.state(['!disabled'] if valid else ['disabled'])\n    if op=='key':\n        ok_so_far = re.match('^[0-9\\-]*$', newval) is not None and len(newval) <= 10\n        if not ok_so_far:\n            errmsg.set(formatmsg)\n        return ok_so_far\n    elif op=='focusout':\n        if not valid:\n            errmsg.set(formatmsg)\n    return valid\ncheck_zip_wrapper = (root.register(check_zip), '%P', '%V')\n\nzip = StringVar()\nf = ttk.Frame(root)\nf.grid(column=0, row=0)\nttk.Label(f, text='Name:').grid(column=0, row=0, padx=5, pady=5)\nttk.Entry(f).grid(column=1, row=0, padx=5, pady=5)\nttk.Label(f, text='Zip:').grid(column=0, row=1, padx=5, pady=5)\ne = ttk.Entry(f, textvariable=zip, validate='all', validatecommand=check_zip_wrapper)\ne.grid(column=1, row=1, padx=5, pady=5)\nbtn = ttk.Button(f, text=\"Process\")\nbtn.grid(column=2, row=1, padx=5, pady=5)\nbtn.state(['disabled'])\nmsg = ttk.Label(f, font='TkSmallCaptionFont', foreground='red', textvariable=errmsg)\nmsg.grid(column=1, row=2, padx=5, pady=5, sticky='w')\n\nroot.mainloop()\n\n\n"
  }
]