Some time ago I made this little app to show images with tkinter, in a canva, letting you browse the image through a listbox on the left. You can go here to see the original code:
There is also another version that uses a label to show the images.
The new version… let’s call it imageslider 1.3
In this version the images fits the screen also when you change the window size. This is obtained binding to <Configure> the root, so that when you change the window size dragging the window it calls the showimg function that you see here below:
def showimg(event): n = lst.curselection() filename = lst.get(n) im = Image.open(filename) im = im.resize((get_window_size()), Image.ANTIALIAS) img = ImageTk.PhotoImage(im) w, h = img.width(), img.height() canvas.image = img canvas.config(width=w, height=h) canvas.create_image(0, 0, image=img, anchor=tk.NW) root.bind("<Configure>", lambda x: showimg(x))
What this function does:
1. get the number of the list selected
2. get the item selected (a string with filename)
3. open the file with Image.open
4. resize it to screen w and h
5. make the canvas the same size
6. add to canvas the image
7. bind to configure the root
The key thing here, is configure. Everytime you change the window size makes the image and canvas be like the root size.
A shrinked version
and even smaller
As you can see, the image strecthes like the window.
The whole code for imageslider 1.3
import tkinter as tk import glob from PIL import Image, ImageTk import os def insertfiles(): # lst.delete(0, tk.END) for filename in glob.glob("*.png"): lst.insert(tk.END, filename) def delete_item(event): n = lst.curselection() os.remove(lst.get(n)) lst.delete(n) def get_window_size(): if root.winfo_width() > 200 and root.winfo_height() >30: w = root.winfo_width() - 200 h = root.winfo_height() - 30 else: w = 200 h = 30 return w, h def showimg(event): n = lst.curselection() filename = lst.get(n) im = Image.open(filename) im = im.resize((get_window_size()), Image.ANTIALIAS) img = ImageTk.PhotoImage(im) w, h = img.width(), img.height() canvas.image = img canvas.config(width=w, height=h) canvas.create_image(0, 0, image=img, anchor=tk.NW) root.bind("<Configure>", lambda x: showimg(x)) root = tk.Tk() root.geometry("800x600+300+50") lst = tk.Listbox(root, width=20) lst.pack(side="left", fill=tk.BOTH, expand=0) lst.bind("<<ListboxSelect>>", showimg) lst.bind("<Control-d>", delete_item) insertfiles() canvas = tk.Canvas(root) canvas.pack() root.mainloop()
Use SVG instead of PNG! Great quality resizing
I had this idea to use svg files instead of png, to have a perfect resizing. I send you to this post to understand how to get an svg into tkinter.
import tkinter as tk import glob from PIL import Image, ImageTk import os from svglib.svglib import svg2rlg from reportlab.graphics import renderPM def insertfiles(): "loads the list of files in the directory" for filename in glob.glob("*.svg"): lst.insert(tk.END, filename) def delete_item(event): "Deletes a file in the list: called by lst.bind('<Control-d>', delete_item)" n = lst.curselection() os.remove(lst.get(n)) lst.delete(n) def get_window_size(): "Returns the width and height of the screen to set images and canvas alike it: called by root.bind <Configure>" root_w = root.winfo_width() if root.winfo_width() > 200 and root.winfo_height() >30: w = root.winfo_width() - 200 h = root.winfo_height() - 30 else: w = 200 h = 30 return w, h def showimg(event): "takes the selected image to show it, called by root.bind <Configure> and lst.bind <<ListboxSelect>>" n = lst.curselection() filename = lst.get(n) drawing = svg2rlg(filename) renderPM.drawToFile(drawing, "temp.png", fmt="PNG") im = Image.open("temp.png") im = im.resize((get_window_size()), Image.ANTIALIAS) img = ImageTk.PhotoImage(im) w, h = img.width(), img.height() canvas.image = img canvas.config(width=w, height=h) canvas.create_image(0, 0, image=img, anchor=tk.NW) root.bind("<Configure>", lambda x: showimg(x)) root = tk.Tk() root.geometry("800x600+300+50") lst = tk.Listbox(root, width=20) lst.pack(side="left", fill=tk.BOTH, expand=0) lst.bind("<<ListboxSelect>>", showimg) lst.bind("<Control-d>", delete_item) insertfiles() canvas = tk.Canvas(root) canvas.pack() root.mainloop()
The video presentation
Here is the repository on github
Subscribe to the newsletter for updates
Tkinter templates
My youtube channel
Twitter: @pythonprogrammi - python_pygame