2016-02-12 71 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

布賴恩的評論舉行了答案:延遲打開文件對話框,直到窗口初始化後解決了問題。當應用程序啓動時,而不是打開文件,創建文件打開方法允許鍵綁定工作,因爲他們應該。