tkinter:在画布上使用滚动条
我正在尝试让一个画布可以滚动。不过,当我试着给画布设置滚动条时,tkinter似乎完全忽略了我最开始设定的画布大小。我试过把它们都放在一个框架里,把画布设置为填满框架,然后再设置框架的大小,但这样做还是会出现同样的问题,除非我把框架也设置为填满窗口,但这不是我想要的。简单来说,我想要一个固定大小的画布,上面有滚动条。我的当前代码是这样的(使用python 3.1):
from tkinter import *
root=Tk()
frame=Frame(root,width=300,height=300)
frame.grid(row=0,column=0)
canvas=Canvas(frame,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))
hbar=Scrollbar(canvas,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(canvas,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=300,height=300)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)
root.mainloop()
2 个回答
-1
下面的代码在我使用 .pack 选项时可以正常运行。但是当我使用 .place 选项时,就不行了。
from tkinter import ttk
import tkinter as tk
root = tk.Tk()
container = ttk.Frame(root)
container.pack()
canvas = tk.Canvas(container)
scrollbar = ttk.Scrollbar(container, orient="vertical", command=canvas.yview)
scrollable_frame = ttk.Frame(canvas)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
x=ttk.Label(scrollable_frame, text="Sample scrolling label")
x.place(x=50,y=50)
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
root.mainloop()
为什么我使用 .place 时它不工作呢?
40
你的滚动条需要把框架(Frame)作为父级,而不是画布(Canvas):
from tkinter import *
root=Tk()
frame=Frame(root,width=300,height=300)
frame.pack(expand=True, fill=BOTH) #.grid(row=0,column=0)
canvas=Canvas(frame,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))
hbar=Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM,fill=X)
hbar.config(command=canvas.xview)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.pack(side=RIGHT,fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=300,height=300)
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)
root.mainloop()
之所以这样做有效,是因为pack
的工作原理。默认情况下,它会尝试把一个容器缩小(或放大)到刚好适合它的子元素。因为在原来的例子中,滚动条是画布的子元素,所以画布就缩小到适合它的大小。
如果你想让滚动条出现在画布里面,诀窍是使用一个额外的框架。把画布和滚动条放在这个内部框架里,把画布的边框去掉,而框架的边框保留。把框架的背景设置成和画布一样,这样就会看起来滚动条是在画布里面了。