Tkinter 专门跟踪窗口大小调整吗?

Tas*_*zer 9 python events tkinter window-resize

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

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()
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

尽管窗口上只有一张画布加上滚动条,但在用户做出与窗口交互的更改之前,调整大小事件会被调用 7 次。当窗口大小调整时,我怎样才能停止这种疯狂并只调用调整大小函数?

jiz*_*AMA 9

effbot 文档中:

<配置>

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

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

更改函数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
Run Code Online (Sandbox Code Playgroud)

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


mar*_*eau 5

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

\n
import tkinter as tk\n\n\nclass Tracker:\n    """ Toplevel windows resize event tracker. """\n\n    def __init__(self, toplevel):\n        self.toplevel = toplevel\n        self.width, self.height = toplevel.winfo_width(), toplevel.winfo_height()\n        self._func_id = None\n\n    def bind_config(self):\n        self._func_id = self.toplevel.bind("<Configure>", self.resize)\n\n    def unbind_config(self):  # Untested.\n        if self._func_id:\n            self.toplevel.unbind("<Configure>", self._func_id)\n            self._func_id = None\n\n    def resize(self, event):\n        if(event.widget == self.toplevel and\n           (self.width != event.width or self.height != event.height)):\n            print(f'{event.widget=}: {event.height=}, {event.width=}\\n')\n            self.width, self.height = event.width, event.height\n\n\nroot = tk.Tk()\nroot.withdraw()\nparent = tk.Toplevel(master=root)\nparent.title('parent')\ncanvas = tk.Canvas(parent)\nscroll_y = tk.Scrollbar(parent, orient="vertical", command=canvas.yview)\nscroll_x = tk.Scrollbar(parent, orient="horizontal", command=canvas.xview)\nframe = tk.Frame(canvas)\n\n# put the frame in the canvas\ncanvas.create_window(0, 0, anchor='nw', window=frame)\n# make sure everything is displayed before configuring the scrollregion\ncanvas.update_idletasks()\n\ncanvas.configure(scrollregion=canvas.bbox('all'),\n                 yscrollcommand=scroll_y.set,\n                 xscrollcommand=scroll_x.set)\n\nscroll_y.pack(fill='y', side='right')\nscroll_x.pack(fill='x', side='bottom')\ncanvas.pack(fill='both', expand=True, side='left')\n\ntracker = Tracker(parent)\ntracker.bind_config()\n\nparent.mainloop()\n\n
Run Code Online (Sandbox Code Playgroud)\n