簡體   English   中英

tkinter 重繪一個可滾動的 canvas

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM