[英]tkinter redraw a scrollable canvas
從另一個 StackOverflow,我得到了這個代碼示例,它顯示了如何在帶有小部件的框架周圍動態調整 canvas 的大小。
import tkinter as tk
class Image(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.wm_geometry("400x150")
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
self.resizable(False,False)
container = tk.Frame(self, relief="sunken", padx=3, pady=3, bd=1)
container.grid(row=0, column=0, sticky="nsew")
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
container.grid_columnconfigure(1, weight=2)
menu = SideMenu(container, self)
menu.grid(row=0,column=0, sticky="nwe")
menu.configure(relief="ridge", padx= 3)
self.frames = {}
startpage = StartPage(container, self)
backuppage = BackupPage(container, self)
restorepage = RestorePage(container, self)
progresspage = ProgressPage(container, self)
self.frames[StartPage] = startpage
self.frames[BackupPage] = backuppage
self.frames[RestorePage] = restorepage
self.frames[ProgressPage] = progresspage
startpage.grid(row=0, column=1, sticky="nsew")
backuppage.grid(row=0, column=1, sticky="nsew")
restorepage.grid(row=0, column=1, sticky="nsew")
progresspage.grid(row=0, column=1, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, bd=1)
startpage_lbl = tk.Label(self, text="Start Page")
startpage_lbl.pack(pady=10, padx=10, fill="both")
self.winfo_toplevel().title("Image")
class BackupPage(tk.LabelFrame):
def __init__(self, parent, controller):
tk.LabelFrame.__init__(self, parent, text="Backup", bd=1)
class RestorePage(tk.LabelFrame):
def __init__(self, parent, controller):
tk.LabelFrame.__init__(self, parent, text="Restore", bd=1)
class SideMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, pady=8)
self.btn_backup = tk.Button(self, text="BACKUP", command= lambda: controller.show_frame(BackupPage))
self.btn_restore = tk.Button(self, text="RESTORE", command= lambda: controller.show_frame(RestorePage))
self.btn_progress = tk.Button(self, text="PROGRESS", command= lambda: controller.show_frame(ProgressPage))
self.btn_backup.pack(side = tk.TOP, fill= tk.X, expand = True)
self.btn_restore.pack(side = tk.TOP, fill= tk.X, expand = True)
self.btn_progress.pack(side = tk.TOP, fill= tk.X, expand = True)
class ProgressPage(tk.LabelFrame):
def __init__(self, parent, controller):
tk.LabelFrame.__init__(self, parent, text="Fortschritt", padx= 3)
self.inner_frame = tk.Frame(self)
self.inner_frame.grid(row=0, column=0, sticky="nw")
self.canvas = tk.Canvas(self.inner_frame, bg="Yellow")
self.canvas.grid(row=0, column=0)
self.vscrollbar = tk.Scrollbar(self.inner_frame, orient=tk.VERTICAL, command=self.canvas.yview)
self.vscrollbar.grid(row=0, column=1, sticky="ns")
self.canvas.configure(yscrollcommand=self.vscrollbar.set)
self.hscrollbar = tk.Scrollbar(self.inner_frame, orient=tk.HORIZONTAL, command=self.canvas.xview)
self.hscrollbar.grid(row=1, column=0, sticky=tk.EW)
self.canvas.configure(xscrollcommand=self.hscrollbar.set)
self.canvas_inner_frame = tk.Frame(self.canvas, bg="Red", bd=2)
for i in range(1, 7+1):
for j in range(1, 7+1):
button = tk.Button(self.canvas_inner_frame, padx=7, pady=7, relief=tk.RIDGE,
text="[%d, %d]" % (i, j))
button.grid(row=i, column=j, sticky='news')
self.canvas.create_window((0,0), window=self.canvas_inner_frame, anchor=tk.NE)
self.canvas_inner_frame.update_idletasks()
self.canvas_inner_frame.bind('<Configure>', lambda e: self.canvas.configure(scrollregion=self.canvas.bbox('all')))
def update_canvas(self, event):
bbox = self.canvas.bbox(tk.ALL)
self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=event.width, height= event.height)
app = Image()
app.mainloop()
編輯:即使根據第一個解決方案正確調整 canvas 的大小后,它仍然會脫離其父級:
如果未繪制 canvas,則 SideMenu 上的按鈕大小正確。 在我看來,canvas 出於某種原因完全忽略了電網。 除此之外,它甚至不繪制內部框架。
當button_frame
調整大小時,您需要更新畫布的滾動區域。 在MyApp.__init__()
末尾添加以下代碼:
buttons_frame.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox('all')))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.