Showing posts with label ticklish Tk. Show all posts
Showing posts with label ticklish Tk. Show all posts

Tuesday, July 2, 2013

world wide widgets

Lots of great Tkinter widges abound on the web and even in the Python source code under demos. Here are my newest favs and some others I've posted previously:
  1. scrolled canvas: uses canvas windows with frames and a scrollbar. credit: python source code demo "canvas-with-scrollbars.py"
  2. treeview table: uses a ttk.Treeview to make a table - and they said it couldn't be done. credit: daniweb
  3. rascally resize tk scrollbars
  4. ttk Notebook demo for Py2
Please feel free to copy these and use them for good. They are covered by this license.

Monday, June 24, 2013

rascally resize tk scrollbars

First, is <pre></pre> the coolest html tag ever? I don't have to worry about non-breaking spaces or line-breaks with pre-formatted text, I just copy and paste my code.
Second, in case you were wondering, I've added a some CSS for inline and block code to my blogger posts. They're in this Gist.
Third, here's a demo of scrollbars and listbox that resize with the window. The trick is in the row and column weights. Set it to a positive number to resize, by using either columnconfigure or rowconfigure.
#! /usr/bin/env python

from Tkinter import *
from ttk import *
import calendar

root = Tk()
root.title('Listy')

master = Frame(root)
master.pack(expand=True, fill=BOTH)
master.columnconfigure(0, weight=1)
# keep scrollbar same width, ie don't resize!
master.columnconfigure(1, weight=0)
master.rowconfigure(0, weight=1)

# y-scrollbar
scrolly = Scrollbar(master, orient=VERTICAL)
scrolly.grid(row=0, column=1, sticky=N+S)

# listbox
listy = Listbox(master)
listy.grid(row=0, column=0, sticky=N+S+E+W)

# content
for m in calendar.month_name:
    listy.insert(END, m)
for d in calendar.day_name:
    listy.insert(END, d)

# bind scrollbar to listbox
listy.config(yscrollcommand=scrolly.set)
scrolly.config(command=listy.yview)

if __name__ == '__main__':
    master.mainloop()
You could do this with the packer geometry manager, by using pack(expand=YES, fill=BOTH) for the listbox and pack(fill=Y) for the scrollbar. The trick is expand which causes the listbox to resize, but not the scrollbar.
#! /usr/bin/env python

from Tkinter import *
from ttk import *
import calendar

root = Tk()
root.title('Listy')

master = Frame(root)
master.pack(expand=True, fill=BOTH)

# y-scrollbar
scrolly = Scrollbar(master, orient=VERTICAL)
scrolly.pack(side=RIGHT, fill=Y)

# listbox
listy = Listbox(master)
listy.pack(side=LEFT, expand=YES, fill=BOTH)

# content
for m in calendar.month_name:
    listy.insert(END, m)
for d in calendar.day_name:
    listy.insert(END, d)

# bind scrollbar to listbox
listy.config(yscrollcommand=scrolly.set)
scrolly.config(command=listy.yview)

if __name__ == '__main__':
    master.mainloop()

ttk Notebook demo for Py2

There is a very nice ttk Notebook demo on a very cleverly named blog called Py in my eye. Note: there are very few differences between the Python 3 version of this demo and the Python 2 version, other than
For a Python 2 version of Jane's demo, see this Gist. To help myself understand what was going on, I forced myself to decompose that stellar example into this super easy demo:
#! /usr/bin/env python

from Tkinter import *
from ttk import *

root = Tk() # create a top-level window

master = Frame(root, name='master') # create Frame in "root"
master.pack(fill=BOTH) # fill both sides of the parent

root.title('EZ') # title for top-level window
# quit if the window is deleted
root.protocol("WM_DELETE_WINDOW", master.quit)

nb = Notebook(master, name='nb') # create Notebook in "master"
nb.pack(fill=BOTH, padx=2, pady=3) # fill "master" but pad sides

# create each Notebook tab in a Frame
master_foo = Frame(nb, name='master-foo')
Label(master_foo, text="this is foo").pack(side=LEFT)
# Button to quit app on right
btn = Button(master_foo, text="foo", command=master.quit)
btn.pack(side=RIGHT)
nb.add(master_foo, text="foo") # add tab to Notebook

# repeat for each tab
master_bar = Frame(master, name='master-bar')
Label(master_bar, text="this is bar").pack(side=LEFT)
btn = Button(master_bar, text="bar", command=master.quit)
btn.pack(side=RIGHT)
nb.add(master_bar, text="bar")

# start the app
if __name__ == "__main__":
    master.mainloop() # call master's Frame.mainloop() method.
    #root.destroy() # if mainloop quits, destroy window
Some notes:
  • The original demo puts the notebook in a frame, in another frame inside the top-level window, but you can just go nb->frame->root, and skip the extra frame. Not sure what you gain or lose.
  • If you want to see the demo decomposed, I converted the original demo as a script in the Gist.
  • You don't have to call Tk() to create a top-level window, Frame will do it for you. Then you can access the window via the master attribute of Frame.
  • If you call the Frame's quit() method, it will destroy the window for you, so the last line, root.destroy(), is not necessary.
  • If you don't bind the "WM_DELETE_WINDOW" protocol to Frame's quit() method, you will get a traceback when root.destroy() is called, saying that it can't destroy the window because it's already been deleted.
  • Use fill=BOTH if your labels and buttons are smaller than the parents they occupy if you want them to extend to both sides.
  • All of these demos are included in your Python distribution. On MS Windows it is here: C:\Python27\tcl\tk8.5\demos
Enjoy!!!

Thursday, May 23, 2013

Tkinter Taylor Solder Spy - Hidden Tk Python Modules

Why is tkFileDialog not listed anywhere in the Python reference? On windows 7 it looks like this:
tkFileDialog.askopenfilename()
tkFileDialog.askopenfilename()
If you were using Tk, which I guess nobody is, why wouldn't you want to know about this? If youhit tab after typing tk in an ipython interpreter, you should see all of these tk dialogs.
tkColorChooser tkCommonDialog tkFileDialog   tkFont         tkMessageBox   tkSimpleDialog
There are also these modules
Tkconstants Tkdnd
but Tkconstant is already imported by Tkinter, and Tkdnd is experimental drag-n-drop, not sure how old it is or if it was every re-categorized as stable. Anyway, the tk modules are all listed on Lundh's effbot and pythonware sites, upythonic wiki, a New Mexico Computer Science website and epydoc's sourceforge Python stdlib directory.

Tuesday, May 21, 2013

Tix, ttk and Tkinter

Tkinter is the graphical package based on Tk that ships standard with most Python builds. But Python 2.7 also has ttk and Tix, which leads to some confusion. Right away this is partially cleared up in the reference for ttk, which describes it as an extension to Tkinter that provides missing widgets. But along comes Tix, which says more or less the same thing. Even more confusing, is that we are encouraged to import ttk as follows:

    >>> from Tkinter import *
    >>> from ttk import *

so that those widgets replaced by ttk will be imported over the older ones in Tkinter.

These include:

WidgetTkinterttk
ButtonXX
CanvasX
CheckbuttonXX
ComboboxX
EntryXX
FrameXX
LabelXX
LabelFrameXX
ListboxX
MenuX
MenubuttonXX
MessageX
NotebookX
OptionMenuX
PanedWindowXX
ProgressbarX
RadiobuttonXX
ScaleXX
ScrollbarXX
SeparatorX
SizegripX
SpinboxXTk8.5.9
TextX
TreeviewX
ToplevelX

I'm not going to include Tix because there are over 40 widgets that are added, but there are two important differences between Tix and ttk.
  • Tix hasn't seen development since 2008 whereas ttk was last upgraded in 2012
  • Tix isn't part of Tk/Tcl - it is a 3rd party add-on.
In general ttk looks newer than Tix. Here are some screen shots of a Tix Meter widget and ttk Progressbar widget.
Tix Meter widget
Tix Meter Widget

ttk Progressbar widget
ttk Progressbar widget

So I think I'm going to stick with ttk imported on top of Tkinter as suggested by Python, and I'll only supplement these widgets with Tix if I absolutely must, since the ttk widgets really do seem better.

Fork me on GitHub