2016-02-25 100 views
2

基於this answer,我想在主圖像下面添加第二個小部件。如何防止圖像在調整大小時填充整個Tkinter窗口?

當用戶調整大小時,該圖像適合窗口。

請參閱從@Marcin的例子:

Resized image

的問題是,如果我添加任何到窗口,奇怪的事情發生了(這裏用文字):

Weird resizing

圖像逐漸增大,直到它填滿整個窗口,第二個小部件消失。

這裏是我的代碼:

from tkinter import * 
from PIL import Image, ImageTk 
from io import BytesIO 
import base64 

root = Tk() 
root.title("Title") 
root.geometry("600x600") 


class ImageFrame(Frame): 
    def __init__(self, master, *pargs): 
     Frame.__init__(self, master, *pargs) 


     self.black_pixel = BytesIO(base64.b64decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=")) 
     self.image = Image.open(self.black_pixel) 

     self.img_copy= self.image.copy() 


     self.background_image = ImageTk.PhotoImage(self.image) 

     self.background = Label(self, image=self.background_image) 
     self.background.pack(fill=BOTH, expand=YES) 
     self.background.bind('<Configure>', self._resize_image) 

     self.width = 1 
     self.height = 1 

    def _resize_image(self,event): 

     new_width = event.width 
     new_height = event.height 

     if new_width != self.width or new_height != self.height: 
      self.width = new_width 
      self.height = new_height 

      self.image = self.img_copy.resize((new_width, new_height)) 

      self.background_image = ImageTk.PhotoImage(self.image) 
      self.background.configure(image = self.background_image) 


img = ImageFrame(root) 
txt = Text(root) 

img.pack(fill=BOTH, expand=YES) 
txt.pack() 

root.mainloop() 

我試圖通過包裝imgtxt有不同的選擇,但它chnanged什麼。

有沒有人有我的做法錯誤的想法,請?

+3

我敢打賭,這與事實有關,事實上,任何事情都會使窗口調整大小,而不僅僅是當用戶拖動窗口句柄時觸發事件。如果回調中的代碼可以改變窗口大小,那麼它可能會導致回調持續發射。 – Kevin

回答

1

在同一個窗口小部件上從<Configure>回調調用.configure很像遞歸,總會有永不結束的風險。

<Configure>觸發event.widthevent.height包括的2個像素的自動填充,所以設置圖像到規定大小增加Label由4個像素再次燒製<Configure>事件的大小。

這不會發生在example by @markus,因爲一旦Label是具有強制幾何的窗口的大小,它將不會再次重新配置,這也是您的程序在圖像完成消耗所有空間後會發生的情況窗戶。

真正快速修復方法是:

new_width = event.width 
    new_height = event.height 

要:

new_width = event.width - 4 
    new_height = event.height - 4 

爲了彌補空間,但我給完全沒有保證,這將始終如一地工作。


這裏是一個不同的實現,它使用一個Canvas而不是FrameLabel

class ImageFrame(Canvas): 
    def __init__(self, master, *pargs ,**kw): 
     Canvas.__init__(self, master, *pargs,**kw) 

     self.black_pixel = BytesIO(base64.b64decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=")) 
     self.img_copy = Image.open(self.black_pixel) 
     self.image = None #this is overriden every time the image is redrawn so there is no need to make it yet 

     self.bind("<Configure>",self._resize_image) 

    def _resize_image(self,event): 
     origin = (0,0) 
     size = (event.width, event.height) 
     if self.bbox("bg") != origin + size: 
      self.delete("bg") 
      self.image = self.img_copy.resize(size) 
      self.background_image = ImageTk.PhotoImage(self.image) 
      self.create_image(*origin,anchor="nw",image=self.background_image,tags="bg") 
      self.tag_lower("bg","all") 

這種方式,而不是重新配置它只是重繪的畫布上的圖像的部件。

+0

這很好,非常感謝你的解釋和解決方法! – Delgan

相關問題