Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python tkinter重新绘制了一个可滚动的画布_Python_Tkinter_Tkinter Canvas - Fatal编程技术网

Python tkinter重新绘制了一个可滚动的画布

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

从另一个StackOverflow中,我得到了这个代码示例,它展示了如何使用小部件动态调整框架周围画布的大小

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')))