Python Tkinter scripts
(August 2005)
This script has been tested with Python 2.3.3 on a Linux operating system.
Main features:
- The "add" button creates new labels which are organized so that the horizontal scrollbar is least used.
- Scrollbars appear and disappear as needed.
Here is the python script:
#!/usr/bin/python
from Tkinter import *
class display(Frame) :
def __init__(self, parent, **options) :
Frame.__init__(self, parent, options)
# creation of internal widgets (scrollbars, canvas)
self.xscrollbar = Scrollbar(self, orient=HORIZONTAL)
self.yscrollbar = Scrollbar(self)
self.canvas = Canvas(self, background="#888")
# connect srollbars
self.canvas.config(
xscrollcommand = self.xscrollbar.set,
yscrollcommand = self.yscrollbar.set )
self.xscrollbar.config(command=self.canvas.xview)
self.yscrollbar.config(command=self.canvas.yview)
self.items = []
self.max_item_width = 0
self.max_item_height = 0
self.bind("<Configure>", self.resize)
self.update_idletasks()
self.draw()
def resize(self, w) :
self.draw()
def add(self, message) :
widget = Label(self.canvas, background="#0F8", text=message)
self.items.append(widget)
self.max_item_width = max(self.max_item_width, widget.winfo_reqwidth())
self.max_item_height = max(self.max_item_height, widget.winfo_reqheight())
self.draw()
def draw_items(self) :
x_border = 10
y_border = 10
# compute the number of columns
w = self.winfo_width()
n_col = w/(x_border+self.max_item_width)
if n_col == 0 : n_col = 1
n = 0
self.canvas.delete("all")
x = x_border
y = y_border
for item in self.items :
id = self.canvas.create_window(x, y, window=item, anchor=NW, tags=("all",))
n = n+1
if n % n_col == 0 :
x = x_border
y = y+self.max_item_height+y_border
else :
x = x+self.max_item_width+x_border
self.canvas.config(scrollregion=self.canvas.bbox(ALL))
def draw_scrollbars(self) :
w = self.winfo_width()
h = self.winfo_height()
bbox = self.canvas.bbox(ALL)
if bbox != None :
bb_x0, bb_y0, bb_x1, bb_y1 = bbox
else :
# no scrollbar needed
self.yscrollbar.place_forget()
self.xscrollbar.place_forget()
return w, h
if h > bb_y1-bb_y0 :
# no y scrollbar needed
self.yscrollbar.place_forget()
if w < bb_x1-bb_x0 :
# x scrollbar needed
delta_y = self.xscrollbar.winfo_reqheight()
self.xscrollbar.place(anchor=SW, rely=1.0, relwidth=1)
h = h-delta_y
if h > bb_y1-bb_y0 :
# y scrollbar need finally
self.yscrollbar.place(anchor=NE, relx=1.0, relheight=1, height=-delta_y)
else :
# y scrollbar needed
delta_x = self.yscrollbar.winfo_reqwidth()
w = w-delta_x
if w < bb_x1-bb_x0 :
# x scrollbar needed
delta_y = self.xscrollbar.winfo_reqheight()
self.xscrollbar.place(anchor=SW, rely=1.0, relwidth=1, width=-delta_x)
h = h - delta_y
else :
delta_y = 0
self.xscrollbar.place_forget()
self.yscrollbar.place(anchor=NE, relx=1.0, relheight=1, height=-delta_y)
return w, h
def draw(self) :
self.draw_items()
w, h = self.draw_scrollbars()
self.canvas.place(width=w, height=h)
def delete_all(self) :
self.canvas.delete("all")
self.items = []
self.draw()
def add_cb() :
global my_display, n, root
my_display.add("hello world %d" % n)
n = n+1
# main part of the program
root = Tk()
n = 0
my_display = display(root, width=100, height=100)
button_panel = Frame(root)
button_panel.pack()
add_button = Button(button_panel, command=add_cb, text="add")
add_button.pack(side=LEFT)
del_button = Button(button_panel, command=my_display.delete_all, text="delete all")
del_button.pack(side=LEFT)
my_display.pack(expand=1, fill=BOTH)
root.mainloop()
This script has been tested with Python 2.4 on a Linux operating system.
Main features:
- thumbnail preview
- convenient keyboard control
shell> ren_view *.jpg
There is the script:
#!/usr/bin/python
import string
from Tkinter import *
import Image
import ImageTk
import os
import re
THUMBNAIL_WIDTH = 300
THUMBNAIL_HEIGHT = 300
automatic_suffix=True
filelist = sys.argv
filelist.pop(0) # removal of the first element which is the name of the program
current_file = None
thumbnail_id = None
photo = None
def display_next_file() :
global thumbnail_id, photo, current_file, automatic_suffix
if thumbnail_id != None : thumbnail_canvas.delete(thumbnail_id)
if len(filelist) == 0 : sys.exit(0)
current_file = filelist.pop(0)
if automatic_suffix :
suffix = re.sub(".*\.", ".", current_file)
suffix_entry.delete(0, END)
suffix_entry.insert(END, suffix)
filename_label.config(text=current_file)
im = Image.open(current_file)
#im = im.resize((THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT))
im.thumbnail((THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT))
print im.size
photo = ImageTk.PhotoImage(im)
thumbnail_id = thumbnail_canvas.create_image(10+THUMBNAIL_WIDTH/2, 10+THUMBNAIL_HEIGHT/2, anchor=CENTER, image=photo)
def rename(current, new) :
dir = os.path.dirname(current)
full_new_path = os.path.join(dir, new)
if os.path.exists(full_new_path) :
i=1
prefix = os.path.join(dir, prefix_entry.get())
user_text = user_entry.get()
suffix = suffix_entry.get()
format = "%s%s.%02d%s"
while os.path.exists(format % (prefix, user_text, i, suffix)) :
i = i+1
full_new_path = format % (prefix, user_text, i, suffix)
print "rename", current, "->", full_new_path
os.rename(current, full_new_path)
def validate(event) :
if user_entry.get() != "" :
rename(current_file, new_name())
user_entry.delete(0, END)
display_next_file()
def new_name() :
prefix = prefix_entry.get()
user_text = user_entry.get()
suffix = suffix_entry.get()
return user_convert(prefix+user_text+suffix)
def user_convert(str) :
return string.replace(str, " ", "_")
def update_result(event) :
result_label.config(text="Resulting file name: "+new_name())
root = Tk()
title_label = Label(root, text="Rename your pictures", font=("Helvetica","14"))
title_label.grid(row=0, columnspan=4, sticky=W)
# prefix
prefix_label = Label(root, text="Prefix:")
prefix_label.grid(row=1, column=0, sticky=W)
prefix_entry = Entry(width=20)
prefix_entry.grid(row=1, column=1)
prefix_entry.bind("<KeyRelease>", update_result)
# suffix
suffix_label = Label(root, text="Suffix:")
suffix_label.grid(row=1, column=2, sticky=W)
suffix_entry = Entry(width=20)
suffix_entry.grid(row=1, column=3)
suffix_entry.bind("<KeyRelease>", update_result)
thumbnail_canvas = Canvas(root, height=THUMBNAIL_HEIGHT+20, width=THUMBNAIL_WIDTH+20)
thumbnail_canvas.grid(row=2, columnspan=4)
filename_label = Label(root, text="(void)")
filename_label.grid(row=3, columnspan=4)
# short description
description = Message(root, text="Enter a description to be used in the filename (leave blank if no change is to be made):", aspect=1200)
description.grid(row=4, columnspan=4, sticky=W)
# user entry
user_entry = Entry(width=30)
user_entry.bind("<Return>", validate)
user_entry.bind("<KeyRelease>", update_result)
user_entry.grid(row=5, columnspan=4);
user_entry.focus_set()
#
result_label = Label(root)
result_label.grid(row=6, columnspan=4)
display_next_file()
root.mainloop()
Points of interest:
- Some variables are local and others are global without obvious distinction:
THUMBNAIL_HEIGHT
is naturally global, whereas thumbnail_id
needs a "global
" instruction to be global, and I do not know why...
- In function
display_next_file
, the variable photo
needs to be global, so that the program keeps a reference on the picture when it exits this function, and can keep displaying this picture.