Tkinter Does Not Suck

  • 21,336 views
Uploaded on

In which I attempt to convince the audience that Tkinter does not, in fact, suck.

In which I attempt to convince the audience that Tkinter does not, in fact, suck.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
21,336
On Slideshare
0
From Embeds
0
Number of Embeds
6

Actions

Shares
Downloads
203
Comments
2
Likes
9

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Tkinter doesn’t suck! Honest! Saturday, 7 November 2009
  • 2. “What GUI toolkit should I use?” – random poster in random forum Saturday, 7 November 2009
  • 3. wxWindows! Saturday, 7 November 2009
  • 4. import wx class Application(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, -1, 'My GUI', size=(300, 200)) panel = wx.Panel(self) sizer = wx.BoxSizer(wx.VERTICAL) panel.SetSizer(sizer) txt = wx.StaticText(panel, -1, 'Hello, world') sizer.Add(txt, 0, wx.TOP|wx.LEFT, 20) self.Centre() self.Show(True) app = wx.App(0) Application(None) app.MainLoop() Saturday, 7 November 2009
  • 5. pyGTK Saturday, 7 November 2009
  • 6. import gtk window = gtk.Window() label = gtk.Label("Hello, world") window.add(label) window.show_all() gtk.main() Saturday, 7 November 2009
  • 7. PyQt! Saturday, 7 November 2009
  • 8. import sys import PyQt4.Qt as qt a=qt.QApplication(sys.argv) w=qt.QLabel("Hello, world") w.show() a.exec_() Saturday, 7 November 2009
  • 9. “whatever you do... Saturday, 7 November 2009
  • 10. ...don’t use Tkinter!” Saturday, 7 November 2009
  • 11. “Tkinter sucks!” Saturday, 7 November 2009
  • 12. import Tkinter as tk root = tk.Tk() tk.Label(root, text="Hello, world").pack() root.mainloop() Saturday, 7 November 2009
  • 13. “yeah, OMG, Tkinter sucks!” Saturday, 7 November 2009
  • 14. I disagree Saturday, 7 November 2009
  • 15. 1. it’s simple to use - rich base widget set - which is not verbose - automatic packing Saturday, 7 November 2009
  • 16. 2. it’s always there on Windows & OS X -- on Linuxes you might need to install an optional package Saturday, 7 November 2009
  • 17. 3. it’s mature first release 1991 8.0 released August 1999 8.5 released December 2007 Saturday, 7 November 2009
  • 18. how I discovered this I had this project that I wanted to be click-to-run, but needed to select a file Looked for a cross-platform “file dialog” solution and found some hacks Then I noticed a reference to Tkinter, and lo and behold... Saturday, 7 November 2009
  • 19. filename = tkFileDialog.askopenfilename(parent=root, filetypes=[('ReStructuredText Files', '.rst .txt'), ('All Files', '.*')], title='Select your presentation file') Saturday, 7 November 2009
  • 20. Saturday, 7 November 2009
  • 21. well, if it can do that... what about the program’s command-line options? Saturday, 7 November 2009
  • 22. Saturday, 7 November 2009
  • 23. self.root = tk.Tk() frame = Tk.Frame(self.root) frame.pack() Tk.Label(frame, text='Bruce, the Presentation Tool!').pack() self.fullscreen = Tk.IntVar() Tk.Checkbutton(frame, text='Fullscreen?', variable=self.fullscreen).pack() # screen selection display = pyglet.window.get_platform().get_default_display() N = len(display.get_screens()) self.screen = Tk.IntVar(0) if N > 1: for n in range(N): Tk.Radiobutton(frame, text="Display on screen %d"%(n+1), variable=self.screen, value=n).pack() self.timer = Tk.IntVar() Tk.Checkbutton(frame, text='Show Timer?', variable=self.timer).pack() self.page_count = Tk.IntVar() Tk.Checkbutton(frame, text='Show Page Count?', variable=self.page_count).pack() self.bullet_mode = Tk.IntVar() Tk.Checkbutton(frame, text='Run in Bullet Mode?', variable=self.bullet_mode).pack() self.source = Tk.IntVar() Tk.Checkbutton(frame, text='Display source in console?', variable=self.source).pack() Tk.Button(frame, text='Play Presentation', command=self.go).pack() Saturday, 7 November 2009
  • 24. specific Tkinter gripes Saturday, 7 November 2009
  • 25. 1. it’s not pretty Saturday, 7 November 2009
  • 26. 1. it’s not pretty 1. it doesn’t look native, 2. fonts are not anti-aliased Saturday, 7 November 2009
  • 27. 2. extending is tricky Saturday, 7 November 2009
  • 28. native look and feel (since Tk 8.0, 1999) Saturday, 7 November 2009
  • 29. native look and feel (since Tk 8.0, 1999) (much improved in Tk 8.5, 2008) Saturday, 7 November 2009
  • 30. native look and feel (since Tk 8.0, 1999) (much improved in Tk 8.5, 2008) (“less ugly but not perfect”) Saturday, 7 November 2009
  • 31. Saturday, 7 November 2009
  • 32. Saturday, 7 November 2009
  • 33. truetype / opentype fonts (since Tk 8.5) Saturday, 7 November 2009
  • 34. 1. Simple to use Saturday, 7 November 2009
  • 35. Widgets Saturday, 7 November 2009
  • 36. import Tkinter as tk root = tk.Tk() tk.Label(root, text="Hello, world").pack() root.mainloop() demo image display label properties: foreground, background, font, ??? Saturday, 7 November 2009
  • 37. import Tkinter as tk root = tk.Tk() tk.Label(root, text="Hello, world").pack() root.mainloop() No point showing the other three lines in other examples Saturday, 7 November 2009
  • 38. from PIL import Image, ImageTk image = ImageTk.PhotoImage(Image.open('kitten.jpg')) tk.Label(root, image=image).pack() Saturday, 7 November 2009
  • 39. def pressed(): print 'You pressed me!' tk.Button(root, text='Press me!', command=pressed).pack() Saturday, 7 November 2009
  • 40. entry = tk.Entry(root) entry.pack() entry.insert(0, 'some text') Saturday, 7 November 2009
  • 41. value = tk.IntVar() tk.Checkbutton(root, text='Checked?', variable=value).pack() Saturday, 7 November 2009
  • 42. value = tk.IntVar() for n in range(4): tk.Radiobutton(root, value=n text="Selection %d"%(n+1), variable=value).pack() Saturday, 7 November 2009
  • 43. value = tk.StringVar(value='One') tk.OptionMenu(root, value, 'One', 'Two', 'Three').pack() 10 minutes Saturday, 7 November 2009
  • 44. listbox = tk.Listbox(root) listbox.pack() listbox.insert(tk.END, "a list entry") for item in ‘one two three four’.split(): listbox.insert(tk.END, item) Saturday, 7 November 2009
  • 45. text = tk.Text(root) text.pack() text.insert(tk.END, '''some text more text''') also allows: - embedding of images and widgets - searching - tagging (identification, useful for properties) - styles Saturday, 7 November 2009
  • 46. scale = tk.Scale(root, from_=0, to=100) scale.pack() Saturday, 7 November 2009
  • 47. w = tk.Canvas(root, width=200, height=100) w.pack() w.create_line(0, 0, 200, 100) w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4)) w.create_rectangle(50, 25, 150, 75, fill="blue") - line (with arrows), arc, image, oval, polygon, rectangle, text, widgets - outline, fill - scrollable (limitable) - picking (with closest) Saturday, 7 November 2009
  • 48. 1. Simple to use Saturday, 7 November 2009
  • 49. Packing Saturday, 7 November 2009
  • 50. rows or columns the pack manager packs into rows or columns the default is column, centered. Saturday, 7 November 2009
  • 51. in the beginning there is a container, and it is empty we’re going to pack this container at the default tk.TOP Saturday, 7 November 2009
  • 52. tk.Button(root, text='Press me!').pack() pack a button Saturday, 7 November 2009
  • 53. tk.Button(root, text='Press me!').pack() tk.Button(root, text='Press me too!').pack() pack a button Saturday, 7 November 2009
  • 54. tk.Button(root, text='Press me!').pack() tk.Button(root, text='Press me too!').pack() tk.Button(root, text='And me!').pack() pack a button Saturday, 7 November 2009
  • 55. tk.Button(root, text='Press me!').pack(side=tk.LEFT) tk.Button(root, text='Press me too!').pack(side=tk.LEFT) tk.Button(root, text='And me!').pack(side=tk.LEFT) pack on tk.LEFT instead Saturday, 7 November 2009
  • 56. tk.Button(root, text='Press me!').pack(side=tk.RIGHT) tk.Button(root, text='Press me too!').pack(side=tk.RIGHT) tk.Button(root, text='And me!').pack(side=tk.RIGHT) pack on tk.RIGHT instead Saturday, 7 November 2009
  • 57. more complex packing? Saturday, 7 November 2009
  • 58. tk.Button(root, text='Press me!').pack() horizontal = tk.Frame(root) horizontal.pack() tk.Button(horizontal, text='Press me too!').pack(side=tk.LEFT) tk.Button(horizontal, text='Press me too!').pack(side=tk.LEFT) Saturday, 7 November 2009
  • 59. grids Saturday, 7 November 2009
  • 60. tk.Button(root, text='Press me!').grid(row=0, column=0) tk.Message(root, text='Pressnmentoo!').grid(row=1, column=0) tk.Button(root, text='And me!').grid(row=1, column=1) those are tk.CENTER “sticky” other options are the 9 points of the compass pack() also allows the sticky side to be specified see I snuck in the multiline “Message” widget there? Saturday, 7 November 2009
  • 61. ... or place Saturday, 7 November 2009
  • 62. Widget values Saturday, 7 November 2009
  • 63. widgets with a variable variable = tk.IntVar() value = variable.get() variable.set(value) Saturday, 7 November 2009
  • 64. text widgets entry = tk.Entry() value = entry.get() entry.delete(0, tk.END) entry.insert(0, value) Saturday, 7 November 2009
  • 65. list boxes listbox = tk.Listbox(root) listbox.pack() for item in ‘one two three four’.split(): listbox.insert(tk.END, item) selected = list.curselection() Saturday, 7 November 2009
  • 66. Styling Saturday, 7 November 2009
  • 67. 2 methods: 1. direct 2. themed (py2.6+, py3k+) Saturday, 7 November 2009
  • 68. tk.Label(root, text="Hello, world!", background='black', foreground='white', font='Courier').pack() Saturday, 7 November 2009
  • 69. tk.Button(root, text="Hello, world!", background='black', foreground='white', font='Courier').pack() some limitations (sometimes depending on your theme) Saturday, 7 November 2009
  • 70. Option 2: Themed Saturday, 7 November 2009
  • 71. from [tT]kinter import ttk lower-case “t” in py3k+ If you want it earlier you can install the tile extension Saturday, 7 November 2009
  • 72. complementary Though the themed widget commands work similarly to the originals, there are important differences. Themed widgets are not a drop-in replacement. In particular, themed widgets generally provide less options for customizing their appearance than regular Tk widgets (e.g. they will often not have options like "-background"). Such changes, if needed (and they should be needed much less often) must be done by defining new widget styles, using the facilities offered by the themed widget package. Saturday, 7 November 2009
  • 73. Implements button, checkbutton, entry, label, menubutton, radiobutton, scale, scrollbar, frame, labelframe, panedwindow Saturday, 7 November 2009
  • 74. Added combobox, notebook, progressbar, separator, sizegrip Saturday, 7 November 2009
  • 75. Not present canvas, listbox, menu, spinbox, text these aren’t really needed Saturday, 7 November 2009
  • 76. “classes” and “styles” >>> from tkinter import ttk >>> l = ttk.Label('hello, world!') >>> l.winfo_class() 'TLabel' >>> l['style'] '' Saturday, 7 November 2009
  • 77. layout example (button) Saturday, 7 November 2009
  • 78. >>> style = ttk.Style() >>> style.layout('TButton') [("Button.border", {"children": [("Button.focus", {"children": [("Button.spacing", {"children": [("Button.label", {"sticky": "nswe"})], "sticky": "nswe"})], "sticky": "nswe"})], "sticky": "nswe", "border": "1"})] Saturday, 7 November 2009
  • 79. element options >>> style = ttk.Style() >>> style.element_options('Button.label') ('-compound', '-space', '-text', '-font', '-foreground', '-underline', '-width', '-anchor', '-justify', '-wraplength', '-embossed', '-image', '-stipple', '-background') Saturday, 7 November 2009
  • 80. style = ttk.Style() style.configure("Red.TLabel", foreground="red", font="Courier 32") ttk.Label(text="Test Styled", style="Red.TLabel").pack() ttk.Label(text="Test Unstyled").pack() Saturday, 7 November 2009
  • 81. switching themes style = ttk.Style() current_theme = style.theme_use() new_theme = style.theme_create(...) style.theme_use(new_theme) Saturday, 7 November 2009
  • 82. Events Saturday, 7 November 2009
  • 83. bind(), unbind() def callback(event): print "clicked at", event.x, event.y frame = Frame(root, width=100, height=100) frame.bind("<Button-1>", callback) Saturday, 7 November 2009
  • 84. <modifier-type-detail> Saturday, 7 November 2009
  • 85. mouse event types mouse button <Button-1>, <Button-2>, <Button-3> mouse drag <B1-Motion> mouse release <ButtonRelease-1>, ... double click <Double-Button-1>, ... triple click <Triple-Button-1>, ... mouse entered <Enter> mouse left <Leave> Saturday, 7 November 2009
  • 86. keyboard event types focus <FocusIn>, <FocusOut> <Enter>, <Delete>, <Left>, specific keys <Right>, ... any key <Key> any text a, b, 1, 2, ... <Shift-Up>, <Alt-Enter>, modified keys <Control-Tab>, ... Saturday, 7 November 2009
  • 87. special event types configuration <Configure> The widget changed size (or location, on some platforms). The new size is provided in the width and height attributes of the event object passed to the callback. Saturday, 7 November 2009
  • 88. Canvas w = tk.Canvas(root, width=400, height=300) w.pack() Saturday, 7 November 2009
  • 89. w.create_line(0, 0, 400, 300) Saturday, 7 November 2009
  • 90. w.create_line(0, 300, 400, 0,fill="red", dash=(4, 4)) Saturday, 7 November 2009
  • 91. w.create_rectangle(150, 125, 250, 175, outline="green", fill="blue") specify corders, outline and fill colors Saturday, 7 November 2009
  • 92. w.create_arc(50, 50, 200, 200, outline="blue", fill="green") Saturday, 7 November 2009
  • 93. w.create_oval(200, 200, 250, 250, outline="blue", fill="green") Saturday, 7 November 2009
  • 94. from PIL import Image, ImageTk image = ImageTk.PhotoImage(Image.open('kitten.jpg')) w.create_image((0, 0), image=image, anchor=tk.NW) Saturday, 7 November 2009
  • 95. Tips Saturday, 7 November 2009
  • 96. self.attributes('-topmost', True) Saturday, 7 November 2009