【问题标题】:Tkinter - How to dynamically resize gradient frames?Tkinter - 如何动态调整渐变帧的大小?
【发布时间】:2021-11-29 07:21:12
【问题描述】:

我想知道如何根据窗口大小自动调整以下渐变框架的大小。

from tkinter import *

class InventorySystem:
    def __init__(self, root):
        self.root = root
        self.root.title("Inventory System")
        self.root.geometry("1366x768")

        j = 0
        colors = ["#007F5F", "#2B9348", "#55A630", "#80B918", "#AACC00", "#BFD200",
                  "#D4D700", "#DDDF00", "#EEEF20", "#FFFF3F"]
        for color in colors:
            Frame(self.root, width = 1366 / len(colors), height = 768,
                  bg = color).place(x = j, y = 0)
            j = j + 1366 / len(colors)

if __name__ == "__main__":
    root = Tk()
    application = InventorySystem(root)
    root.mainloop()

【问题讨论】:

  • 您可以在绑定到root 窗口的'<Configure>' 事件回调函数中调整渐变帧的大小。
  • 非常感谢马蒂诺。基本上,我是 Tkinter 的新手,实际上我不知道如何使用“”,我想看看有人在我的代码中如何使用它来理解方案和机制。如果您可以运行并修复粘贴的代码,我将不胜感激,否则非常感谢您的建议。

标签: python user-interface tkinter gradient frame


【解决方案1】:

您想要做的事情有些复杂,因此即使您不只是学习如何使用 tkinter 也可能具有挑战性(只是因为它的文档记录太差而加剧了这种情况)。因此,我创建了一个示例,说明如何根据您问题中的代码进行操作。

(对我来说)一件不直观的事情是 Event 处理窗口的 <'Configure>' 事件的“回调”函数会被窗口本身调用以及其中的所有小部件 - 如果您没有意识到这就是发生的事情,这可能会非常令人困惑。

我还更改并重新格式化了您的代码,以更紧密地遵循PEP 8 - Style Guide for Python Code 的建议,我强烈建议您阅读并开始关注这些建议。请特别注意,我将您的通配符 from tkinter import * 更改为首选的 import tkinter as tk — 请参阅 Should wildcard import be avoided?

import tkinter as tk

WIDTH, HEIGHT = 1366, 768  # Initial size of root window.

class InventorySystem:
    # Gradient frame colors.
    COLORS = ["#007F5F", "#2B9348", "#55A630", "#80B918", "#AACC00",
              "#BFD200", "#D4D700", "#DDDF00", "#EEEF20", "#FFFF3F"]

    def __init__(self, root):
        self.root = root
        self.root.title("Inventory System")
        self.root.geometry(f'{WIDTH}x{HEIGHT}')
        self.width, self.height = WIDTH, HEIGHT  # Size of root window.
        self.create_gradient_frames()

    def create_gradient_frames(self):
        """Create a gradient frame for each color."""
        self.gradient_frames = []
        colors = self.COLORS  # Alias for local access.
        gradient_frame_width = round(self.width / len(colors))
        gradient_frame_height = self.height

        for i, color in enumerate(colors):
            frame = tk.Frame(self.root, width=gradient_frame_width,
                             height=gradient_frame_height, bg=color)
            frame.place(x=i * gradient_frame_width,
                        y=self.height - gradient_frame_height)
            self.gradient_frames.append(frame)

    def update_gradient_frames(self):
        """Update size and position of all gradient frames."""
        gradient_frame_width = round(self.width / len(self.COLORS))
        gradient_frame_height = self.height

        for i, frame in enumerate(self.gradient_frames):
            frame.config(width=gradient_frame_width, height=gradient_frame_height)
            frame.place(x=i * gradient_frame_width,
                        y=self.height - gradient_frame_height)

    def on_resize(self, event):
        """Root window size change event handler."""
        # Needed following because event handler is called for the container win
        # and all its child widgets but we only need to handle container itself.
        if event.widget.master is not None:  # Not the root window?
            return  # Ignore.

        width, height = root.winfo_width(), root.winfo_height()  # Current size.
        if width != self.width or height != self.height:  # Updated?
            self.width, self.height = width, height  # Track change.
            self.update_gradient_frames()


if __name__ == "__main__":
    root = tk.Tk()
    application = InventorySystem(root)
    root.bind('<Configure>', application.on_resize)  # Bind callback function to event.
    root.mainloop()

这是正在调整大小的窗口的屏幕截图:

【讨论】:

  • 您好 Martineau,非常感谢您的回答,它运行良好,这将是我下一步改进的起点。我的目标是了解小部件动态调整大小背后的机制,并通过您的解释,我相信我可以实现我的目标。再次感谢您,并祝您一切顺利。 PS。为糟糕的问题陈述道歉!
  • JackFrost:很高兴听到您发现它在处理动态调整大小方面很有帮助,尽管这显然不是处理它的最简单方法——正如@acw1668 的回答所充分说明的那样。 ;¬)
【解决方案2】:

你可以使用.place()相对选项

# relative width of each frame
# 1.0 means same width of parent
relw = 1 / len(colors) 
for j, color in enumerate(colors):
    Frame(self.root, bg=color).place(relx=j*relw, y=0, relwidth=relw, relheight=1)

详见place()官方文档。

【讨论】:

  • 非常感谢 acw1668,您的解决方案非常清晰且运行良好。祝您有美好的一天,再次感谢您...
  • @JackFrost:我认为你真的应该接受这个答案,而不是我的答案——这显然是 IMO 更好的答案。
猜你喜欢
  • 2011-03-31
  • 2016-06-29
  • 2012-11-07
  • 1970-01-01
  • 2018-10-09
  • 2014-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多