2013-05-13 267 views
3

我正在尋找一種方法,使Tkinter的框架的行爲有點像這樣在調整大小:調整大小的Tkinter框架固定縱橫比

from Tkinter import * 
w = Tk() 
w.aspect(1,1,1,1) 
w.mainloop() 

所以我想這個代碼在這裏:

import Tkinter as tk 
from Tkconstants import * 
r=tk.Tk() 
content_frame=tk.Frame(r,borderwidth=5,relief=GROOVE) 
content_frame.grid(row=0,column=0,sticky=(N,S,E,W)) 
tk.Label(content_frame,text='content').pack() 
pad_frame=tk.Frame(r,borderwidth=5,relief=GROOVE) 
pad_frame.grid(row=1,column=0,sticky=(N,S,E,W)) 
tk.Label(pad_frame,text='-pad-').pack() 
r.rowconfigure(0, weight=1) 
r.rowconfigure(1, weight=1) 
r.columnconfigure(0, weight=1) 
r.mainloop() 

它基本上創建了2個框架,其中一個應該包含一些內容(在我的應用程序中,此框架包含可調整大小的mathplotlib圖形),另一個僅用於填充。

要表現在調整大小遵循以下規則:

  • 與固定縱橫比內容框架調整大小(假設它總是需要是正方形)
  • 墊架佔據了剩餘的(垂直)空間

任何想法?我一直在閱讀手冊一段時間,似乎無法找到合適的東西。

-Daniel

+0

你爲什麼不移除填充並只使用'aspect'? – 2013-05-13 14:04:30

+0

這是我真正想要的簡化案例。整個事情是嵌入在一個更大的接口,所以我不能使用Windows /頂級/ ... 和框架沒有.aspect()方法。 – 2013-05-14 09:28:10

回答

4

至少有一對夫婦的方式來解決這個問題。最簡單的IMO就是讓您的填充小部件成爲您的內容小部件的容器,然後使用place明確設置內容小部件的寬度和高度。這是其中place優於gridpack的其中一種邊緣情況。

在下面的例子中,我創建了一個函數,可以傳入內容框架,填充框架和高寬比。然後通過容器的高寬比和大小來限制內容框的大小。它會使內容窗口填充X維中的容器,然後適當地設置高度。如果生成的窗口太高而不可見,則將最大高度設置爲容器的高度,然後調整寬度。

我試圖保持大部分代碼不受問題的影響,儘管這不完全是我通常選擇編碼的方式。我已經給出了不同的顏色,所以很容易看到發生了什麼。

import Tkinter as tk 
from Tkconstants import * 
r=tk.Tk() 

def set_aspect(content_frame, pad_frame, aspect_ratio): 
    # a function which places a frame within a containing frame, and 
    # then forces the inner frame to keep a specific aspect ratio 

    def enforce_aspect_ratio(event): 
     # when the pad window resizes, fit the content into it, 
     # either by fixing the width or the height and then 
     # adjusting the height or width based on the aspect ratio. 

     # start by using the width as the controlling dimension 
     desired_width = event.width 
     desired_height = int(event.width/aspect_ratio) 

     # if the window is too tall to fit, use the height as 
     # the controlling dimension 
     if desired_height > event.height: 
      desired_height = event.height 
      desired_width = int(event.height * aspect_ratio) 

     # place the window, giving it an explicit size 
     content_frame.place(in_=pad_frame, x=0, y=0, 
      width=desired_width, height=desired_height) 

    pad_frame.bind("<Configure>", enforce_aspect_ratio) 

pad_frame = tk.Frame(borderwidth=0, background="bisque", width=200, height=200) 
pad_frame.grid(row=0, column=0, sticky="nsew", padx=10, pady=20) 
content_frame=tk.Frame(r,borderwidth=5,relief=GROOVE, background="blue") 
tk.Label(content_frame,text='content').pack() 
set_aspect(content_frame, pad_frame, aspect_ratio=2.0/1.0) 
r.rowconfigure(0, weight=1) 
r.columnconfigure(0, weight=1) 

r.mainloop() 

如果包含的小部件的容易調整容器的大小,這將工作最好。如果內部有複雜的小部件佈局,則當窗口縮小到自然尺寸以下時,如果不適合,某些小部件可能會被切斷。

+0

工程就像一個魅力。非常有用,謝謝你。如果我在Tkinter的GUI編程方面有更多的經驗,我可能也會做得不一樣,但我對整個事情都比較陌生。再次感謝偉大的代碼。 – 2013-05-17 09:55:21

2

你可以綁定到<Configure>事件函數包含的內容和填充幀Frame。調整窗口大小時將觸發<Configure>事件。通過更新行和列的權重,使用事件的寬度和高度屬性來修復內容框架的大小:rowconfigurecolumnconfigure

您需要在容器框架中有兩行和兩列纔能有方形內容框架。有了一個高大的窗戶,你需要在第二行填充。而且,如果窗口很寬,則需要在第二列填充。

工作的示例:

import Tkinter as tk 
from Tkconstants import * 


class Application(tk.Frame): 
    def __init__(self, master, width, height): 
     tk.Frame.__init__(self, master) 
     self.grid(sticky=N + S + E + W) 
     master.rowconfigure(0, weight=1) 
     master.columnconfigure(0, weight=1) 
     self._create_widgets() 
     self.bind('<Configure>', self._resize) 
     self.winfo_toplevel().minsize(150, 150) 

    def _create_widgets(self): 
     self.content = tk.Frame(self, bg='blue') 
     self.content.grid(row=0, column=0, sticky=N + S + E + W) 

     self.rowconfigure(0, weight=1) 
     self.rowconfigure(1, weight=1) 
     self.columnconfigure(0, weight=1) 
     self.columnconfigure(1, weight=1) 

    def _resize(self, event): 
     '''Modify padding when window is resized.''' 
     w, h = event.width, event.height 
     w1, h1 = self.content.winfo_width(), self.content.winfo_height() 
     print w1, h1 # should be equal 
     if w > h: 
      self.rowconfigure(0, weight=1) 
      self.rowconfigure(1, weight=0) 
      self.columnconfigure(0, weight=h) 
      self.columnconfigure(1, weight=w - h) 
     elif w < h: 
      self.rowconfigure(0, weight=w) 
      self.rowconfigure(1, weight=h - w) 
      self.columnconfigure(0, weight=1) 
      self.columnconfigure(1, weight=0) 
     else: 
      # width = height 
      self.rowconfigure(0, weight=1) 
      self.rowconfigure(1, weight=0) 
      self.rowconfigure(0, weight=1) 
      self.columnconfigure(1, weight=0) 

root = tk.Tk() 
app = Application(master=root, width=100, height=100) 
app.mainloop() 
+0

也完美的作品。也會接受你的答案,但我只能接受一個...對此抱歉。 不過,非常感謝。 – 2013-05-17 09:56:45

+0

謝謝,Bryan的答案好多了。 – 2013-05-17 10:21:18

相關問題