在tkinter中使用askopenfilename对话框时,键绑定不起作用

问题描述 投票:1回答:2

我正在开发一个简单的应用程序,用于读取和显示zip文件中的图像文件序列,使用python 3.4和tkinter,就像你可能用来阅读.cbz漫画书文件一样。理想情况下,我想绑定左右键分别显示上一个和下一个图像。如果我在代码中指定zip文件的名称,这可以正常工作;但是,如果我使用filedialog.askopenfilename()对话框指定文件,则键盘键绑定不再起作用。

我认为这是由于焦点问题,我已经尝试将焦点设置为键绑定到的标签(使用label.focus_set()方法和askopenfilename()对话框的父选项)但没有成功。

代码如下。任何有关这方面的帮助将不胜感激,因为它开始让我疯狂。

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()
python tkinter key-bindings
2个回答
1
投票

布莱恩的评论得出了答案:延迟打开文件对话直到窗口初始化后解决了问题。应用程序启动时,创建文件打开方法不是在应用程序启动时打开文件,而是允许键绑定按预期工作。


0
投票

如果你在root.update()之前和之后调用askopenfilename(),那么键绑定就可以了。

© www.soinside.com 2019 - 2024. All rights reserved.