2016-02-12 60 views
0

我工作的一个简单的应用程序来读取和使用Python 3.4与Tkinter的一个zip文件内显示的图像文件序列,就像你可以使用阅读.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() 
+0

您声明image_list为空列表每次acquire_image_list被称为所以只有在列表中的当前文件名。一个简单的打印语句将会告诉你这是否是问题。将image_list传递给该函数,并将其从函数中返回或使用实例对象 - > self.image_list。 –

+0

我隐约记得几年前阅读一个bug报告,主要涉及在主窗口出现之前在窗口上打开一个对话框。在使用文件对话框之前,您可能会尝试等待UI初始化之后。 –

+0

@CurlyJoe - 只有在选择zip文件后才能调用acquire_image_list一次。它应该每次都清空,以便列表只包含来自一个文件的图像。 –

回答

1

布赖恩的评论举行了答案:延迟打开文件对话框,直到窗口初始化后解决了问题。当应用程序启动时,而不是打开文件,创建文件打开方法允许键绑定工作,因为他们应该。