I’m trying to insert a scrollbar into a canvas filled with buttons (where, buttons can be switched to clickable text as well).
With the code below, the window seems OK.
However, when I uncomment the lines with the scrollbar, the window geometry scrambles.
Can anybody give a hand to figure out what’s wrong with the code?
System: Windows 10, python 3.9.6.
import tkinter as tk class tWindow(tk.Tk): frame = None canvas = None scrollbar = None def __init__(self, **kwargs): super().__init__(**kwargs) self.geometry("640x480+50+50") self.setup_frame() self.setup_canvas() def setup_frame(self): self.frame = tk.Frame(master=self, width=640, height=480) self.frame.configure(bg="#003163") self.frame.place(x=0, y=0) def setup_canvas(self): self.update() self.canvas = tk.Canvas(master=self.frame, bg="#006331", width=int(self.frame.winfo_width() / 4), height=self.frame.winfo_height()) self.canvas.place(x=0, y=0) self.update() # self.scrollbar = tk.Scrollbar(master=self.canvas, orient=tk.VERTICAL) # self.scrollbar.pack(side=tk.RIGHT, fill=tk.BOTH, expand=tk.TRUE) # self.canvas.configure(yscrollcommand=self.scrollbar.set) # self.scrollbar.configure(command=self.canvas.yview) # self.update() tmp_pos = 0 for i in range(20): btn_tmp = tk.Button(master=self.canvas, text=f"testing testing testing testing testing {i:02} ...", justify=tk.LEFT, wraplength=self.canvas.winfo_width(), bg="#00c0c0", fg="#000000") btn_tmp.place(x=0, y=tmp_pos) self.update() tmp_pos = btn_tmp.winfo_y() + btn_tmp.winfo_height() def main(): app = tWindow() app.mainloop() if __name__ == "__main__": main()
Advertisement
Answer
See comments in code as additional to the link I have provided. Also see why update is considered harmfull and how do I organize my tkinter gui for more details.
import tkinter as tk class tWindow(tk.Tk): frame = None canvas = None scrollbar = None def __init__(self, **kwargs): super().__init__(**kwargs) self.geometry("640x480+50+50") self.setup_frame() self.setup_canvas() def setup_frame(self): self.frame = tk.Frame(master=self, width=640, height=480,bg="#003163") self.frame.pack(side='left',fill='both',expand=True)##pack left ## self.frame.place(x=0, y=0) ##place requiers too think to much def setup_canvas(self): ## self.update() ##update is harmfull self.canvas = tk.Canvas(master=self.frame, bg='orange',#"#006331", width=int(self.frame.winfo_reqwidth() / 4), height=self.frame.winfo_reqheight()) ##use reqwidth/hight to avoid the use of update. ##It takes the requested size instead the actual self.canvas.pack(side='left') self.canvas_frame = tk.Frame(self.canvas,bg="#006331") ##frame to pack buttons in canvas self.canvas.create_window((0,0), window=self.canvas_frame, anchor="nw") ##show frame in canvas self.scrollbar = tk.Scrollbar(master=self.frame, orient=tk.VERTICAL) self.scrollbar.pack(side='left',fill='y') self.canvas.configure(yscrollcommand=self.scrollbar.set) self.scrollbar.configure(command=self.canvas.yview) self.canvas_frame.bind('<Configure>',self.oncanvasconfigure) ##bind event configure to update the scrollregion for i in range(20): btn_tmp = tk.Button(master=self.canvas_frame, text=f"testing testing testing testing testing {i:02} ...", justify=tk.LEFT, wraplength=self.canvas.winfo_reqwidth(), bg="#00c0c0", fg="#000000") btn_tmp.pack() def oncanvasconfigure(self,event): self.canvas.configure(scrollregion=self.canvas.bbox("all")) def main(): app = tWindow() app.mainloop() if __name__ == "__main__": main()