简体   繁体   中英

Tkinter Canvas & Scrollbar

I have found several questions and answers related to this but none of the solutions make me understand why this code doesn't work:

root=tk.Tk()

vscrollbar = tk.Scrollbar(root)

c= tk.Canvas(root,background = "#D2D2D2",yscrollcommand=vscrollbar.set)

vscrollbar.config(command=c.yview)
vscrollbar.pack(side=tk.LEFT, fill=tk.Y) 

f=tk.Frame(c) #Create the frame which will hold the widgets

c.pack(side="left", fill="both", expand=True)
c.create_window(0,0,window=f)

testcontentA = tk.Label(f,wraplength=350 ,text=r"Det er en kendsgerning, at man bliver distraheret af læsbart indhold på en side, når man betragter dens websider, som stadig er på udviklingsstadiet. Der har været et utal af websider, som stadig er på udviklingsstadiet. Der har været et utal af variationer, som er opstået enten på grund af fejl og andre gange med vilje (som blandt andet et resultat af humor).")
testcontentB = tk.Button(f,text="anytext")
testcontentA.pack()
testcontentB.pack()

f.pack()

c.config(scrollregion=c.bbox("all"))

root.mainloop()

I have a tkinter window which has dynamically generated content - which means need to be able to scroll down if there are two many widgets to be displayed on screen. I hope to be able to populate the frame 'f' with the widgets and then use the canvas.create_window() function to display it in a scrollable way.

Right now the window is displayed but the scrollbar is not enabled - its like the scrollregion is not correct or the link between the scrollbar and the canvas is not correct.

If you are embedding a frame in a canvas you must use create_window , not pack . The first step is to remove f.pack() .

Second, you need to set the bbox after tkinter has had a chance to display the widgets since their size cannot be computed until they are actually drawn on the screen.

A simple way to accomplish that is to call root.update() before calling c.config(scrollregion=c.bbox("all")) , or schedule that command to be run with after_idle .

Another bug in your code (I'm assuming...) is that you create the window at (0,0) but don't set the anchor. That means that the internal frame will be centered at (0,0) when I'm guessing you want the upper left corner to be at (0,0).

Change your create_window call to look like this:

c.create_window(0,0,window=f, anchor='nw')
import tkinter as tk

root=tk.Tk()

vscrollbar = tk.Scrollbar(root)

c= tk.Canvas(root,background = "#D2D2D2",yscrollcommand=vscrollbar.set)

vscrollbar.config(command=c.yview)
vscrollbar.pack(side=tk.LEFT, fill=tk.Y) 

f=tk.Frame(c) #Create the frame which will hold the widgets

c.pack(side="left", fill="both", expand=True)

#Updated the window creation
c.create_window(0,0,window=f, anchor='nw')

#Added more content here to activate the scroll
for i in range(100):
    tk.Label(f,wraplength=350 ,text=r"Det er en kendsgerning, at man bliver distraheret af læsbart indhold på en side, når man betragter dens websider, som stadig er på udviklingsstadiet. Der har været et utal af websider, som stadig er på udviklingsstadiet. Der har været et utal af variationer, som er opstået enten på grund af fejl og andre gange med vilje (som blandt andet et resultat af humor).").pack()
    tk.Button(f,text="anytext").pack()

#Removed the frame packing
#f.pack()

#Updated the screen before calculating the scrollregion
root.update()
c.config(scrollregion=c.bbox("all"))

root.mainloop()

Thanks to Bryan Oakley for the great answer.

It's easy, you store c.create in a tuple!

from tkinter import *
root = Tk()
c = Canvas(root, width=500, height=400).pack()
scroll = c.create_rectangle(225,175,175,225,fill='black'),c.create_rectangle(225,175,275,225)
while True:
      x1 = 1
      c.move(scroll,x1,0)
canvas.mainloop()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM