Tkinter 使用固定纵横比调整大小

时间:2020-12-23 21:50:19

标签: python tkinter

我正在尝试使用 Tkinter 在 Python 中创建 GUI。我有一个 Frame 会出现一些控制输入,还有一个 Frame 会出现 Matplotlib 图。该情节将位于它自己的 Frame 中。

问题是,我希望包含情节的 Frame 保持其纵横比,以便情节可见且实用。我找到了 this stackoverflow question,但它似乎不起作用,即使我负责更新代码以使用 Python 3.8 。但是当我运行程序时,包含情节的 Frame 是不可见的。控制台中没有错误。

这是我的代码:

import tkinter as tk

def center(win, w = None, h = None):
    # sets the window's minimal size and centers it.
    win.update() # updates the window to get it's minimum working size

    # if no size is given, keep the minimum size
    width = w if w else win.winfo_width()
    height = h if h else win.winfo_height()

    # compute position for the window to be central
    x = (win.winfo_screenwidth() - width) // 2
    y = (win.winfo_screenheight() - height) // 2

    # set geomet and minimum size
    win.geometry("{}x{}+{}+{}".format(width, height, x, y))
    win.minsize(width, height)

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)

window = tk.Tk()

window.columnconfigure(0, weight=1, minsize=300)
window.rowconfigure(0, weight=1, minsize=300)

# Frame with the main content.
content = tk.Frame(
    window,
)
content.grid(row=0, column=0, padx=5, pady=5, sticky="nesw")

# Frame with the plot. It lays inside the "content" Frame
plot_frame = tk.Frame(
    content,
    bg = "blue",
    width = 300,
    height = 300
)
tk.Label(plot_frame,text='Some Plot').pack()
# Frame for padding apparently necessary to have the resized Frame
pad_frame = tk.Frame(content, borderwidth=0, background="bisque", width=200, height=200)
pad_frame.grid(row=0, column=0, sticky="nsew", padx=10, pady=20)
# calls function to fix the aspect ratio
set_aspect(plot_frame, pad_frame, aspect_ratio=16/9) 
content.rowconfigure(0, weight=1)
content.columnconfigure(0, weight=1)

# Frame containing the setting controls
window.columnconfigure(1, weight=0, minsize=200)
settings = tk.Frame(
    window,
    bg = "red"
)
settings.grid(row=0, column=1, padx=5, pady=5, sticky="nesw")

# usual Tkinter stuff
center(window)
window.title("Some Program")
window.mainloop()

提前致谢。

1 个答案:

答案 0 :(得分:0)

好的,我自己发现了我的错误。对于任何感兴趣的人:诀窍是在固定纵横比 Frame 之前定义填充 Frame。所以就我而言,我应该这样做:

# Frame for padding apparently necessary to have the resized Frame
pad_frame = tk.Frame(content, borderwidth=0, background="bisque", width=200, height=200)
pad_frame.grid(row=0, column=0, sticky="nsew", padx=10, pady=20)
# Frame with the plot. It lays inside the "content" Frame
plot_frame = tk.Frame(
    content,
    bg = "blue",
    width = 300,
    height = 300
)
tk.Label(plot_frame,text='Some Plot').pack()
# calls function to fix the aspect ratio
set_aspect(plot_frame, pad_frame, aspect_ratio=16/9) 
content.rowconfigure(0, weight=1)
content.columnconfigure(0, weight=1)

代替:

# Frame with the plot. It lays inside the "content" Frame
plot_frame = tk.Frame(
    content,
    bg = "blue",
    width = 300,
    height = 300
)
tk.Label(plot_frame,text='Some Plot').pack()
# Frame for padding apparently necessary to have the resized Frame
pad_frame = tk.Frame(content, borderwidth=0, background="bisque", width=200, height=200)
pad_frame.grid(row=0, column=0, sticky="nsew", padx=10, pady=20)
# calls function to fix the aspect ratio
set_aspect(plot_frame, pad_frame, aspect_ratio=16/9) 
content.rowconfigure(0, weight=1)
content.columnconfigure(0, weight=1)