Tkinter canvas y barra de desplazamiento

He encontrado varias preguntas y respuestas relacionadas con esto, pero ninguna de las soluciones me hace entender por qué este código no funciona:

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() 

Tengo una ventana tkinter que tiene contenido generado dinámicamente, lo que significa que debo poder desplazarme hacia abajo si hay dos widgets para mostrar en la pantalla. Espero poder rellenar el marco ‘f’ con los widgets y luego usar la función canvas.create_window () para mostrarlo de forma desplazable.

En este momento se muestra la ventana, pero la barra de desplazamiento no está habilitada, es como si la región de desplazamiento no fuera correcta o el enlace entre la barra de desplazamiento y el canvas no fuera correcto.

Si está incrustando un marco en un canvas, debe utilizar create_window , no pack . El primer paso es eliminar f.pack() .

En segundo lugar, debe configurar el bbox después de que tkinter haya tenido la oportunidad de mostrar los widgets, ya que su tamaño no se puede calcular hasta que se dibujen en la pantalla.

Una forma sencilla de hacerlo es llamar a root.update() antes de llamar a c.config(scrollregion=c.bbox("all")) , o progtwigr ese comando para que se ejecute con after_idle .

Otro error en su código (supongo …) es que crea la ventana en (0,0) pero no establece el ancla. Eso significa que el marco interno se centrará en (0,0) cuando supongo que desea que la esquina superior izquierda esté en (0,0).

Cambia tu llamada a create_window para que se vea así:

 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() 

Gracias a Bryan Oakley por la gran respuesta.

Es fácil, almacenar c.create en una tupla!

 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()