Reputation: 31
I'm working on a simple app for reading and displaying sequences of image files from within a zip file using python 3.4 with tkinter, like you might use for reading .cbz comic book files. Ideally I'd like to bind the left and right keys to show the last and next images respectively. This works fine if I specify the name of the zip file in the code; however, if I use filedialog.askopenfilename() dialogue box to specify the file, then the keyboard key bindings no longer work.
I assumed this was due to a focus issue, and I've tried setting the focus to the label to which the keys are bound (both using the label.focus_set() method and the parent option of the askopenfilename() dialogue) without success.
Code is below. Any help on this would be greatly appreciated, as it's starting to drive me nuts.
from tkinter import *
from tkinter import filedialog
import io
from PIL import Image, ImageTk
import zipfile
class ComicDisplay():
def __init__(self, master):
frame = Frame(master)
frame.pack(fill='both', expand=1)
self.parent = master
self.fname = ""
self.label = Label(frame, bg="brown", height=500)
self.current_zip_file = filedialog.askopenfilename(filetypes=[(zip, "*.zip")])
# self.current_zip_file = "C:\\Users\\Alexis\\Dropbox\\Photos.zip"
self.image_list = self.acquire_image_list(self.current_zip_file)
self.current_image_number = 0
self.pil_image = self.acquire_image(self.current_zip_file, self.image_list[self.current_image_number])
self.tk_image = ImageTk.PhotoImage(self.pil_image)
self.parent.title(self.fname)
self.label.configure(image=self.tk_image)
self.label.focus_set()
self.label.bind("<Configure>", self.image_resizing)
self.label.bind("<Left>", self.get_last_image)
self.label.bind("<Right>", self.get_next_image)
self.label.bind("<Button-1>", self.get_next_image)
self.label.pack(padx=5, pady=5, fill='both', expand=1)
def acquire_image_list(self, zip_file):
image_list = []
with zipfile.ZipFile(zip_file, "r") as myFile:
for filename in myFile.namelist():
image_list.append(filename)
image_list.sort()
return image_list
def acquire_image(self, zip_file, image_file):
with zipfile.ZipFile(zip_file, "r") as myFile:
self.fname = image_file
image_bytes = myFile.read(image_file)
data_stream = io.BytesIO(image_bytes)
pil_image = Image.open(data_stream)
pil_image = self.image_sizer(pil_image)
return pil_image
def image_sizer(self, image_file, window_size=500):
w, h = image_file.size
if w > h:
image_file_height = int(h*(window_size/w))
image_file = image_file.resize((window_size, image_file_height), Image.ANTIALIAS)
else:
image_file_width = int(w*(window_size/h))
image_file = image_file.resize((image_file_width, window_size), Image.ANTIALIAS)
return image_file
def image_resizing(self, event):
new_height = root.winfo_height() - 14
new_size_image = self.image_sizer(self.pil_image, new_height)
self.tk_image = ImageTk.PhotoImage(new_size_image)
self.label.configure(image=self.tk_image)
def get_next_image(self, event):
if self.current_image_number >= len(self.image_list)-1:
self.current_image_number = 0
else:
self.current_image_number += 1
self.update_image()
def get_last_image(self, event):
if self.current_image_number == 0:
self.current_image_number = len(self.image_list)-1
else:
self.current_image_number -= 1
self.update_image()
def update_image(self):
self.fname = self.image_list[self.current_image_number]
self.pil_image = self.acquire_image(self.current_zip_file, self.image_list[self.current_image_number])
self.tk_image = ImageTk.PhotoImage(self.pil_image)
self.parent.title(self.fname)
self.image_resizing(None)
root = Tk()
app = ComicDisplay(root)
root.mainloop()
Upvotes: 1
Views: 516
Reputation: 410
If you call root.update()
before and after askopenfilename()
, the key bindings work.
Upvotes: 0
Reputation: 31
Bryan's comment held the answer: delaying the open file dialogue until after the window was initialized solved the problem. Instead of opening the file when the app starts, creating a file open method allows the key bindings to work as they should.
Upvotes: 2