Python tkinter重新绘制了一个可滚动的画布
从另一个StackOverflow中,我得到了这个代码示例,它展示了如何使用小部件动态调整框架周围画布的大小Python tkinter重新绘制了一个可滚动的画布,python,tkinter,tkinter-canvas,Python,Tkinter,Tkinter Canvas,从另一个StackOverflow中,我得到了这个代码示例,它展示了如何使用小部件动态调整框架周围画布的大小 import tkinter as tk class Image(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.wm_geometry("400x150") se
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()
将tkinter作为tk导入
类映像(tk.tk):
定义初始化(self,*args,**kwargs):
tk.tk.\uuuuu初始化(self,*args,**kwargs)
自身wm_几何(“400x150”)
self.grid\u column配置(0,权重=1)
self.grid_rowconfigure(0,权重=1)
自我调整大小(False,False)
容器=tk.Frame(self,relief=“sunken”,padx=3,pady=3,bd=1)
container.grid(行=0,列=0,sticky=“nsew”)
container.grid_rowconfigure(0,权重=1)
container.grid\u column配置(0,权重=1)
container.grid\u column配置(1,重量=2)
菜单=侧菜单(容器,自身)
menu.grid(行=0,列=0,sticky=“nwe”)
菜单配置(relief=“ridge”,padx=3)
self.frames={}
起始页=起始页(容器,自身)
备份=备份(容器,自身)
restorepage=restorepage(容器,自身)
progresspage=progresspage(容器,自身)
自帧[起始页]=起始页
self.frames[备份]=备份
self.frames[RestorePage]=RestorePage
self.frames[ProgressPage]=ProgressPage
startpage.grid(行=0,列=1,sticky=“nsew”)
backuppage.grid(行=0,列=1,sticky=“nsew”)
restorepage.grid(行=0,列=1,sticky=“nsew”)
progresspage.grid(行=0,列=1,sticky=“nsew”)
自显示帧(起始页)
def显示画面(自身,续):
帧=自身帧[续]
frame.tkraise()
类起始页(传统框架):
定义初始化(自、父、控制器):
tk.Frame.\uuuuu init\uuuuu(self,parent,bd=1)
起始页=tk.标签(self,text=“起始页”)
起始页包装(pady=10,padx=10,fill=“两者”)
self.winfo_toplevel().title(“图像”)
类备份(tk.LabelFrame):
定义初始化(自、父、控制器):
tk.LabelFrame.\uuuu init\uuuuu(self,parent,text=“Backup”,bd=1)
类别恢复页面(tk.LabelFrame):
定义初始化(自、父、控制器):
tk.LabelFrame.\uuuu init\uuuu(self,parent,text=“Restore”,bd=1)
类侧菜单(tk.Frame):
定义初始化(自、父、控制器):
tk.Frame.\uuuu init\uuuu(self,parent,pady=8)
self.btn_backup=tk.按钮(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)
类进度页(tk.LabelFrame):
定义初始化(自、父、控制器):
tk.LabelFrame.\uuuu init\uuuuu(self,parent,text=“Fortschritt”,padx=3)
self.internal_frame=tk.frame(self)
self.internal_frame.grid(行=0,列=0,sticky=“nw”)
self.canvas=tk.canvas(self.inner_frame,bg=“黄色”)
self.canvas.grid(行=0,列=0)
self.vscrollbar=tk.Scrollbar(self.internal\u frame,orient=tk.VERTICAL,command=self.canvas.yview)
self.vscrollbar.grid(行=0,列=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(行=1,列=0,粘性=tk.EW)
configure(xscrollcommand=self.hscrollbar.set)
self.canvas\u inner\u frame=tk.frame(self.canvas,bg=“Red”,bd=2)
对于范围(1,7+1)内的i:
对于范围(1,7+1)内的j:
按钮=tk.按钮(self.canvas\u内框,padx=7,pady=7,relief=tk.RIDGE,
text=“[%d,%d]”(i,j))
网格(行=i,列=j,粘性='news')
self.canvas.create\u window((0,0),window=self.canvas\u inner\u frame,anchor=tk.NE)
self.canvas\u inner\u frame.update\u idletasks()
self.canvas\u internal\u frame.bind(“”,lambda e:self.canvas.configure(scrollregion=self.canvas.bbox('all'))
def更新画布(自身、事件):
bbox=self.canvas.bbox(tk.ALL)
self.canvas.configure(scrollregion=self.canvas.bbox(“全部”),width=event.width,height=event.height)
app=Image()
app.mainloop()
编辑:
即使根据第一个解决方案正确调整画布的大小,它仍然会脱离其父级:
如果未绘制画布,则侧菜单上的按钮大小正确。在我看来,画布出于某种原因完全忽略了网格。此外,它甚至不绘制内部框架。调整
按钮的大小时,需要更新画布的滚动区域。将以下代码添加到MyApp的末尾。uu init_uuu()
:
buttons\u frame.bind(“”,lambda e:canvas.configure(scrollregion=canvas.bbox('all'))
当添加新小部件时,按钮框
应自动调整大小。它会调整大小,但容纳按钮框的画布不会调整大小。您不需要调整画布的大小,但是每当调整按钮_框架
的大小时,需要更新其滚动区域
。更新滚动区域的最佳方法是什么?谢谢你把我引向正确的方向这仍然不起作用。画布不尊重其边界,并脱离其父画布。请看一下我上面提供的图片。我编辑了代码,您的解决方案是否实现似乎并不重要。现在画布根本不显示其内部框架。
buttons_frame.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox('all')))