首页 > 解决方案 > 如何使用 python 3.8 在 tkinter 的画布中创建滚动条

问题描述

我已经创建了一个画布 c,我想在画布中放一个滚动条来向下和向上滚动我放在画布中的所有东西(我打算放很多东西)。但是滚动条不起作用。我做错了什么?

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

标签: pythonpython-3.xtkintercanvasscrollbar

解决方案


这里有几个问题。首先,标签不是画布项目,它们是您自己网格化到根的小部件。(虽然您确实将画布作为其父级,但这是行不通的,但由于画布的工作方式,它实际上只是将其传递给根而不是出错——这很好,但这是有原因的方式。)

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

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

您真正需要弄清楚的是,您是否想要滚动画布或滚动一些小部件(如标签、按钮等)。如果真的想要滚动画布,请查看http://effbot.org/zone/tkinter -scrollbar-patterns.htm#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()

如果您实际上只是想要一个滚动区域,您可以在其中放置您想要的任何小部件,那么网上人们似乎建议使用滚动画布并在其中放置一个窗口,然后在该窗口中添加您的项目。所以你在正确的轨道上做那件事。您还希望每次移动事物时都发生滚动区域配置,而不仅仅是在制作时发生一次。这是您所拥有的修改后的版本:

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

PS关于您制作的标签列表......如果您一遍又一遍地输入内容,这是一个好兆头,表明有一种更简单的方法可以做您想做的事情。因为无论如何你都会有一个 for 循环,所以我把那部分移到了那里。


推荐阅读