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()
CodePudding user response:
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()