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.
JavaScript
x
47
47
1
import tkinter as tk
2
3
class tWindow(tk.Tk):
4
frame = None
5
canvas = None
6
scrollbar = None
7
8
def __init__(self, **kwargs):
9
super().__init__(**kwargs)
10
self.geometry("640x480+50+50")
11
self.setup_frame()
12
self.setup_canvas()
13
14
def setup_frame(self):
15
self.frame = tk.Frame(master=self, width=640, height=480)
16
self.frame.configure(bg="#003163")
17
self.frame.place(x=0, y=0)
18
19
def setup_canvas(self):
20
self.update()
21
self.canvas = tk.Canvas(master=self.frame, bg="#006331",
22
width=int(self.frame.winfo_width() / 4), height=self.frame.winfo_height())
23
self.canvas.place(x=0, y=0)
24
self.update()
25
26
# self.scrollbar = tk.Scrollbar(master=self.canvas, orient=tk.VERTICAL)
27
# self.scrollbar.pack(side=tk.RIGHT, fill=tk.BOTH, expand=tk.TRUE)
28
# self.canvas.configure(yscrollcommand=self.scrollbar.set)
29
# self.scrollbar.configure(command=self.canvas.yview)
30
# self.update()
31
32
tmp_pos = 0
33
34
for i in range(20):
35
btn_tmp = tk.Button(master=self.canvas, text=f"testing testing testing testing testing {i:02} ...",
36
justify=tk.LEFT, wraplength=self.canvas.winfo_width(), bg="#00c0c0", fg="#000000")
37
btn_tmp.place(x=0, y=tmp_pos)
38
self.update()
39
tmp_pos = btn_tmp.winfo_y() + btn_tmp.winfo_height()
40
41
def main():
42
app = tWindow()
43
app.mainloop()
44
45
if __name__ == "__main__":
46
main()
47
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.
JavaScript
1
53
53
1
import tkinter as tk
2
3
class tWindow(tk.Tk):
4
frame = None
5
canvas = None
6
scrollbar = None
7
8
def __init__(self, **kwargs):
9
super().__init__(**kwargs)
10
self.geometry("640x480+50+50")
11
self.setup_frame()
12
self.setup_canvas()
13
14
def setup_frame(self):
15
self.frame = tk.Frame(master=self, width=640, height=480,bg="#003163")
16
self.frame.pack(side='left',fill='both',expand=True)##pack left
17
## self.frame.place(x=0, y=0) ##place requiers too think to much
18
19
def setup_canvas(self):
20
## self.update() ##update is harmfull
21
self.canvas = tk.Canvas(master=self.frame, bg='orange',#"#006331",
22
width=int(self.frame.winfo_reqwidth() / 4), height=self.frame.winfo_reqheight())
23
##use reqwidth/hight to avoid the use of update.
24
##It takes the requested size instead the actual
25
self.canvas.pack(side='left')
26
27
self.canvas_frame = tk.Frame(self.canvas,bg="#006331")
28
##frame to pack buttons in canvas
29
self.canvas.create_window((0,0), window=self.canvas_frame, anchor="nw")
30
##show frame in canvas
31
32
self.scrollbar = tk.Scrollbar(master=self.frame, orient=tk.VERTICAL)
33
self.scrollbar.pack(side='left',fill='y')
34
35
self.canvas.configure(yscrollcommand=self.scrollbar.set)
36
self.scrollbar.configure(command=self.canvas.yview)
37
self.canvas_frame.bind('<Configure>',self.oncanvasconfigure)
38
##bind event configure to update the scrollregion
39
40
for i in range(20):
41
btn_tmp = tk.Button(master=self.canvas_frame, text=f"testing testing testing testing testing {i:02} ...",
42
justify=tk.LEFT, wraplength=self.canvas.winfo_reqwidth(), bg="#00c0c0", fg="#000000")
43
btn_tmp.pack()
44
def oncanvasconfigure(self,event):
45
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
46
47
def main():
48
app = tWindow()
49
app.mainloop()
50
51
if __name__ == "__main__":
52
main()
53