调整 tkinter 中内容的大小 canvas
Resize contents inside tkinter canvas
我正在尝试制作一个 canvas,其中包含一个带有标签的 window,当 window 调整大小时,标签将调整大小。这是我的代码。
import tkinter as tk
main_win = tk.Tk()
main_win.test_number = 0
main_canvas = tk.Canvas(master=main_win, borderwidth=2, relief='ridge', highlightthickness=0)
main_canvas.pack(side='top', fill='both', expand=True, padx=30, pady=30)
canvas_frame = tk.Frame(master=main_canvas, borderwidth=2, relief='ridge')
main_canvas.create_window((4,4), window=canvas_frame, anchor='nw')
def _on_config(widget):
main_win.test_number +=1
print(main_win.test_number)
canvas_width = main_canvas.winfo_width()
widget.config(width=canvas_width)
inner_lbl_frame_1 = tk.Frame(master=canvas_frame, borderwidth=2, relief='ridge')
inner_lbl_frame_1.pack(side='top', fill='x', expand=True)
lbl_test_1 = tk.Label(master=inner_lbl_frame_1, text="Test |")
lbl_test_1.pack(side='left', padx=5, pady=5)
lbl_verify_1 = tk.Label(master=inner_lbl_frame_1, text="To Verify |")
lbl_verify_1.pack(side='left', padx=5, pady=5)
lbl_conclusion_1 = tk.Label(master=inner_lbl_frame_1, text="If Resize Works")
lbl_conclusion_1.pack(side='left', fill='x', expand=True, padx=5, pady=5)
inner_lbl_frame_2 = tk.Frame(master=canvas_frame, borderwidth=2, relief='ridge')
inner_lbl_frame_2.pack(side='top', fill='x', expand=True)
lbl_test_2 = tk.Label(master=inner_lbl_frame_2, text="Test |")
lbl_test_2.pack(side='left', padx=5, pady=5)
lbl_verify_2 = tk.Label(master=inner_lbl_frame_2, text="To Verify |")
lbl_verify_2.pack(side='left', padx=5, pady=5)
lbl_conclusion_2 = tk.Label(master=inner_lbl_frame_2, text="If Resize Works")
lbl_conclusion_2.pack(side='left', fill='x', expand=True, padx=5, pady=5)
main_win.bind("<Configure>", lambda e: _on_config(canvas_frame))
main_win.mainloop()
当我 运行 这样做时,它陷入了无限循环。我试图自己研究这个问题,但是,由于这是一个有点具体的问题,我还没有看到任何答案。请解释为什么这不起作用以及我如何让它变得更好..
为了解决我使用的帧数,它是为了布局目的。我将添加更多包含标签的标签框以保存大量视觉数据,但这是我能写的最好的最小可重现示例。
我正在使用 Python 3.9.2.
您不应在 main_win
上绑定事件,因为它将继承给其子项,包括 canvas_frame
。所以在_on_change()
里面改变canvas_frame
的宽度会触发事件并再次调用函数,从而导致递归循环。
您应该改为绑定 main_canvas
并使用 main_canvas.itemconfigure()
更改框架的宽度:
...
# save the item ID of the frame
frame_id = main_canvas.create_window((4,4), window=canvas_frame, anchor='nw')
def _on_config(event, widget_id):
main_win.test_number += 1
print(main_win.test_number)
# use itemconfigure(...) on the passed widget_id
event.widget.itemconfigure(widget_id, width=event.width-8)
...
# bind on main_canvas instead of main_win
main_canvas.bind('<Configure>', lambda e: _on_config(e, frame_id))
...
我正在尝试制作一个 canvas,其中包含一个带有标签的 window,当 window 调整大小时,标签将调整大小。这是我的代码。
import tkinter as tk
main_win = tk.Tk()
main_win.test_number = 0
main_canvas = tk.Canvas(master=main_win, borderwidth=2, relief='ridge', highlightthickness=0)
main_canvas.pack(side='top', fill='both', expand=True, padx=30, pady=30)
canvas_frame = tk.Frame(master=main_canvas, borderwidth=2, relief='ridge')
main_canvas.create_window((4,4), window=canvas_frame, anchor='nw')
def _on_config(widget):
main_win.test_number +=1
print(main_win.test_number)
canvas_width = main_canvas.winfo_width()
widget.config(width=canvas_width)
inner_lbl_frame_1 = tk.Frame(master=canvas_frame, borderwidth=2, relief='ridge')
inner_lbl_frame_1.pack(side='top', fill='x', expand=True)
lbl_test_1 = tk.Label(master=inner_lbl_frame_1, text="Test |")
lbl_test_1.pack(side='left', padx=5, pady=5)
lbl_verify_1 = tk.Label(master=inner_lbl_frame_1, text="To Verify |")
lbl_verify_1.pack(side='left', padx=5, pady=5)
lbl_conclusion_1 = tk.Label(master=inner_lbl_frame_1, text="If Resize Works")
lbl_conclusion_1.pack(side='left', fill='x', expand=True, padx=5, pady=5)
inner_lbl_frame_2 = tk.Frame(master=canvas_frame, borderwidth=2, relief='ridge')
inner_lbl_frame_2.pack(side='top', fill='x', expand=True)
lbl_test_2 = tk.Label(master=inner_lbl_frame_2, text="Test |")
lbl_test_2.pack(side='left', padx=5, pady=5)
lbl_verify_2 = tk.Label(master=inner_lbl_frame_2, text="To Verify |")
lbl_verify_2.pack(side='left', padx=5, pady=5)
lbl_conclusion_2 = tk.Label(master=inner_lbl_frame_2, text="If Resize Works")
lbl_conclusion_2.pack(side='left', fill='x', expand=True, padx=5, pady=5)
main_win.bind("<Configure>", lambda e: _on_config(canvas_frame))
main_win.mainloop()
当我 运行 这样做时,它陷入了无限循环。我试图自己研究这个问题,但是,由于这是一个有点具体的问题,我还没有看到任何答案。请解释为什么这不起作用以及我如何让它变得更好..
为了解决我使用的帧数,它是为了布局目的。我将添加更多包含标签的标签框以保存大量视觉数据,但这是我能写的最好的最小可重现示例。
我正在使用 Python 3.9.2.
您不应在 main_win
上绑定事件,因为它将继承给其子项,包括 canvas_frame
。所以在_on_change()
里面改变canvas_frame
的宽度会触发事件并再次调用函数,从而导致递归循环。
您应该改为绑定 main_canvas
并使用 main_canvas.itemconfigure()
更改框架的宽度:
...
# save the item ID of the frame
frame_id = main_canvas.create_window((4,4), window=canvas_frame, anchor='nw')
def _on_config(event, widget_id):
main_win.test_number += 1
print(main_win.test_number)
# use itemconfigure(...) on the passed widget_id
event.widget.itemconfigure(widget_id, width=event.width-8)
...
# bind on main_canvas instead of main_win
main_canvas.bind('<Configure>', lambda e: _on_config(e, frame_id))
...