如何使用 python 3.8 在 tkinter 的 canvas 中创建滚动条

How to create a scrollbar in a canvas in tkinter using python 3.8

我创建了一个 canvas c 并且我想在 canvas 中放置一个滚动条来向下和向上滚动我在 canvas 中放置的所有内容(我是打算放很多东西)。但是滚动条不起作用。我做错了什么?

from tkinter import *

root = Tk()

c=Canvas(root)
c.config(width=160,height=100)
c.grid(row=0,column=0)

Scrb=Scrollbar(root,orient=VERTICAL)
Scrb.grid(column=2)
c.config(scrollregion=c.bbox("all"))
c.config(yscrollcommand=Scrb.set)
Scrb.config(command=c.yview)

label = Label(c, text="this is to fill room")
label1 = Label(c, text="this is to fill room")
label2 = Label(c, text="this is to fill room")
label3 = Label(c, text="this is to fill room")
label4 = Label(c, text="this is to fill room")
label5 = Label(c, text="this is to fill room")
label6 = Label(c, text="this is to fill room")
list_labels = [label,label1,label2,label3,label4,label5,label6]

for i in range(0,7):
    list_labels[i].grid(row=i,column=0)

root.mainloop()

这里有一些问题。首先,标签不是 canvas 项目,它们是它们自己的小部件,您正在网格化到根目录中。 (虽然您确实将 canvas 作为它们的父级,但这不起作用,但由于 canvas 的工作方式,它实际上只是将其传递给根而不是错误——这会很好,但这是有原因的。)

接下来,您用第一个标签(其中 i=0)覆盖了放置 canvas 的 0, 0 网格,因此 canvas 甚至不显示。

接下来,您将滚动条放在第 2 列并跳过第 1 列。这没有任何问题(也许您稍后会在第 1 列中放一些东西,谁知道呢,)我只是想确保您知道那里发生了什么。

您真正需要弄清楚的是,如果您想要滚动 canvas 或滚动一些小部件(如标签、按钮等)。如果真的想要滚动 canvas,请使用看看 http://effbot.org/zone/tkinter-scrollbar-patterns.htm#canvas 为了您的方便,如果您只是想复制和粘贴,我已经从那里包含了一个片段(在 canvas 上添加了一些元素,所以您可以真正看到滚动):

from tkinter import *
root = Tk()
frame = Frame(root, bd=2, relief=SUNKEN)

frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)

xscrollbar = Scrollbar(frame, orient=HORIZONTAL)
xscrollbar.grid(row=1, column=0, sticky=E+W)

yscrollbar = Scrollbar(frame)
yscrollbar.grid(row=0, column=1, sticky=N+S)

canvas = Canvas(frame, bd=0, scrollregion=(0, 0, 1000, 1000),
                xscrollcommand=xscrollbar.set,
                yscrollcommand=yscrollbar.set)

canvas.grid(row=0, column=0, sticky=N+S+E+W)

xscrollbar.config(command=canvas.xview)
yscrollbar.config(command=canvas.yview)

for i in range(100):
    canvas.create_rectangle(
        i/10*100, i%10*100, i/10*100+50, i%10*100+50,
        fill='green')

frame.pack()

如果你真的只是想要一个滚动区域,你可以在其中放置任何你想要的小部件,网上的人似乎推荐的是滚动 canvas 并在其中放置一个 window ,然后在 window 中添加您的项目。所以你是在正确的轨道上这样做。您还希望 scrollregion 配置在每次移动时都发生,而不是在制作时发生一次。 这是您所拥有内容的修改版本:

from tkinter import *

root = Tk()
frame = Frame(root, width=160, height=100)
c=Canvas(frame)
c.config(width=160,height=100)
c.pack(side=LEFT)

def innerFrameGo(_):
    c.configure(scrollregion=c.bbox('all'))

inner_frame = Frame(c)
inner_frame.bind("<Configure>", innerFrameGo)
inner_frame_id = c.create_window(0,0,window=inner_frame,anchor=NW)

Scrb=Scrollbar(frame,orient=VERTICAL)
Scrb.pack(side=RIGHT, fill=Y)
c.configure(yscrollcommand=Scrb.set)
Scrb.config(command=c.yview)

frame.pack()

for i in range(0,7):
    label = Label(inner_frame, text="this is to fill room")
    label.grid(row=i, column=0)

root.mainloop()

P.S。关于您制作的标签列表……如果您一遍又一遍地输入内容,这是一个好兆头,表明有更简单的方法来完成您想要做的事情。无论如何你都会有一个 for-loop,我把那部分移到了那里。