繁体   English   中英

Tkinter 轨道 window 专门调整大小?

[英]Tkinter track window resize specifically?

我正在编写一个小程序,它打算在 window 大小发生变化时运行调整大小的方法。 出于这个原因,我使用了toplevel.bind("<Configure>", self.resize) 虽然这确实适用于调整大小,但该方法会被调用数百次:滚动时,使用某些按钮时,即使 window 大小不会随这些操作中的任何一个而改变。 如何绑定事件,以便仅在更改 window 大小时调用它?

import tkinter as tk

def resize(event):
    print("widget", event.widget)
    print("height", event.height, "width", event.width)

parent = tk.Toplevel()
canvas = tk.Canvas(parent)
scroll_y = tk.Scrollbar(parent, orient="vertical", command=canvas.yview)
scroll_x = tk.Scrollbar(parent, orient="horizontal", command=canvas.xview)
frame = tk.Frame(canvas)

# put the frame in the canvas
canvas.create_window(0, 0, anchor='nw', window=frame)
# make sure everything is displayed before configuring the scrollregion
canvas.update_idletasks()

canvas.configure(scrollregion=canvas.bbox('all'), 
                yscrollcommand=scroll_y.set,
                xscrollcommand=scroll_x.set)

scroll_y.pack(fill='y', side='right')
scroll_x.pack(fill='x', side='bottom')
canvas.pack(fill='both', expand=True, side='left')

parent.bind("<Configure>", resize)

parent.mainloop()

Output:

widget .!toplevel
height 200 width 200
widget .!toplevel.!scrollbar
height 286 width 17
widget .!toplevel.!scrollbar2
height 17 width 382
widget .!toplevel.!canvas
height 269 width 382
widget .!toplevel
height 286 width 399
widget .!toplevel
height 286 width 399
widget .!toplevel.!can

尽管只有一个 canvas 加上 window 上的滚动条,但在用户更改与 window 交互之前,调整大小事件被调用了 7 次。 当 window 确实被调整大小时,我怎样才能停止这种疯狂并只调用调整大小 function?

effbot 文档中

<配置>

小部件更改了大小(或位置,在某些平台上)。 新尺寸在传递给回调的事件 object 的宽度高度属性中提供。

当您运行代码时,它将在 window 中绘制这些小部件,因此 window 的宽度和高度将发生变化。 您可以使用if语句来检查Toplevel的宽度和高度是否发生了变化。

更改 function resize()并在代码中初始化全局变量:

def resize(event):
    global window_width, window_height
    if event.widget.widgetName == "toplevel":
        if (window_width != event.width) and (window_height != event.height):
            window_width, window_height = event.width,event.height
            print(f"The width of Toplevel is {window_width} and the height of Toplevel "
                  f"is {window_height}")

window_width, window_height = 0, 0

您可以通过使用 class (OOP) 来避免global变量。

据我所知,当您将“<Configure>”事件绑定到根或顶级 window 时,它也会绑定到它包含的每个小部件——唯一的解决方法是过滤掉所有其他调用。 幸运的是,这并不太难。 为了避免使用全局变量,我定义了一个 class 来处理脏细节。

import tkinter as tk


class Tracker:
    """ Toplevel windows resize event tracker. """

    def __init__(self, toplevel):
        self.toplevel = toplevel
        self.width, self.height = toplevel.winfo_width(), toplevel.winfo_height()
        self._func_id = None

    def bind_config(self):
        self._func_id = self.toplevel.bind("<Configure>", self.resize)

    def unbind_config(self):  # Untested.
        if self._func_id:
            self.toplevel.unbind("<Configure>", self._func_id)
            self._func_id = None

    def resize(self, event):
        if(event.widget == self.toplevel and
           (self.width != event.width or self.height != event.height)):
            print(f'{event.widget=}: {event.height=}, {event.width=}\n')
            self.width, self.height = event.width, event.height


root = tk.Tk()
root.withdraw()
parent = tk.Toplevel(master=root)
parent.title('parent')
canvas = tk.Canvas(parent)
scroll_y = tk.Scrollbar(parent, orient="vertical", command=canvas.yview)
scroll_x = tk.Scrollbar(parent, orient="horizontal", command=canvas.xview)
frame = tk.Frame(canvas)

# put the frame in the canvas
canvas.create_window(0, 0, anchor='nw', window=frame)
# make sure everything is displayed before configuring the scrollregion
canvas.update_idletasks()

canvas.configure(scrollregion=canvas.bbox('all'),
                 yscrollcommand=scroll_y.set,
                 xscrollcommand=scroll_x.set)

scroll_y.pack(fill='y', side='right')
scroll_x.pack(fill='x', side='bottom')
canvas.pack(fill='both', expand=True, side='left')

tracker = Tracker(parent)
tracker.bind_config()

parent.mainloop()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM