[英]Resizing Tkinter Frames with fixed aspect-ratio
我正在尋找一種方法來使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圖),而另一個框架僅用於填充。
遵循以下規則調整大小:
有任何想法嗎? 我已經閱讀了一段時間的手冊,似乎找不到合適的東西。
-丹尼爾
至少有兩種方法可以解決此問題。 最簡單的IMO是將padding小部件作為內容小部件的容器,然后使用place
顯式設置內容小部件的寬度和高度。 這是邊緣place
比grid
或pack
首選的邊緣情況之一。
在下面的示例中,我創建了一個函數,該函數可讓您傳遞內容框架,填充框架和寬高比。 然后,它通過縱橫比和容器的大小來約束內容框架的大小。 它將使內容窗口在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()
如果包含的窗口小部件的內容可以輕松調整為容器的大小,則這將是最好的選擇。 如果其中的小部件布局復雜,則當窗口縮小到其自然大小以下時,如果某些小部件不適合,則可能會被切掉。
您可以將函數綁定到包含內容框架和填充框架的Frame
的<Configure>
事件。 調整窗口大小時將觸發<Configure>
事件。 使用事件的width和height屬性通過使用rowconfigure
和columnconfigure
更新行和列的權重來固定內容框架的大小
在容器框架中需要兩行兩列才能有一個方形的內容框架。 如果窗口很高,則需要在第二行中填充。 對於寬闊的窗口,您需要在第二欄中填充。
一個工作示例:
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()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.