簡體   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