Python 3.x 是否可以使按钮在画布内滚动?

Python 3.x 是否可以使按钮在画布内滚动?,python-3.x,tkinter,tkinter-canvas,Python 3.x,Tkinter,Tkinter Canvas,我一直在尝试使画布内的按钮可滚动,但它不会滚动 我试着把它放在列表框、画布和框架中,但都不起作用。我什么都试过了,但现在还是不知道该怎么办 from tkinter import * FrameU = Tk() frameN=Frame(FrameU,width=540,height=800,bg="#A0522D") frameN.place(x=0,y=0,relx=.2,rely=.2) canvas=Canvas(frameN,bg="#A0522D",width=400,height

我一直在尝试使画布内的按钮可滚动,但它不会滚动

我试着把它放在列表框、画布和框架中,但都不起作用。我什么都试过了,但现在还是不知道该怎么办

from tkinter import *

FrameU = Tk()
frameN=Frame(FrameU,width=540,height=800,bg="#A0522D")
frameN.place(x=0,y=0,relx=.2,rely=.2)
canvas=Canvas(frameN,bg="#A0522D",width=400,height=800)
scrollbar = Scrollbar(frameN, orient = VERTICAL,width=20,relief=SUNKEN)
scrollbar.pack(side=RIGHT, fill=Y)
scrollbar.config(command=canvas.yview)
canvas.config(width=540,height=800,relief=SUNKEN)
canvas.config(yscrollcommand=scrollbar.set)



mylist=Listbox(canvas,bg="#A0522D",width=100,height=41,bd=5,highlightthickness=0,yscrollcommand=scrollbar.set )
for i in range(100):
    mylist.insert(END, i)

b = Button(canvas,bg="blue",width=5,height=5)
b.place(rely=.5,relx=.5)

mylist.config(yscrollcommand=scrollbar.set)
mylist.pack(side=LEFT,fill=BOTH)
canvas.pack(side=LEFT)

我没有收到任何错误或任何东西,但是如果我将它放在我的列表框中,它会显示在“范围内(100)”中:“它会显示在画布中”!frame.!canvas.!Listbox.!button”

可滚动按钮。你是说按钮的位置会随着滚动条滑块的移动而改变?乍一看,在最简单的情况下,这似乎是不可能的

但是您可以将一个回调函数绑定到滚动条上,该函数将随着鼠标移动滚动条滑块而同步更改按钮位置。以下是一个工作示例:

from tkinter import *
from tkinter import ttk

rx, ry = 0.45, 0.45           # the button position (relative)

root=Tk()

wCanvas, hCanvas = 400, 350   # size of canvas
w1, h1 = 800, 700             # size of scrollable area

vBar = ttk.Scrollbar(root, orient = VERTICAL)
can1 = Canvas(root, scrollregion = (0,0,w1,h1), width = wCanvas, height = hCanvas, yscrollcommand = vBar.set)
vBar['command'] = can1.yview

vBar.pack(side=RIGHT,fill=Y)
can1.pack()

can1.create_line(10, 10, 100, 100)   # for canvas scrolling confirmation only

but1 = Button(can1)
but1.place(relx = rx, rely = ry)

def VscrollBarMove(event):  # callback function
    but1.place(relx = rx, rely = ry + vBar.get()[0])  # Scrollbar.get() returns a tuple with relative positions of upper (for vertical scrollbar) and lower edges of a slider

vBar.bind('<B1-Motion>', VscrollBarMove)

root.mainloop()

我喜欢这个答案,我已经试过了。虽然效果不错,但我还是有点困惑。如果我想添加更多按钮,我需要更改或添加什么。我尝试添加另一个按钮,但是按钮的位置不会改变,只有1dt按钮的位置会改变。所有人都需要-将第二个(以及下一个)按钮的处理添加到相同的回调函数中。我在回答中添加了这个案例的例子。我还有一个问题。当我滚动时,按钮会随之下降。当我向下滚动时,如何更改按钮向上的方向?您需要将rely=ry+vBar.get()[0]中的操作从“+”更改为“-”。如果你用“relx”代替“rely”,你甚至可以改变移动的方向。对于can1。对于scrollregion,如果我不想侧边滚动,我可以将宽度设为0吗?或者是其他原因?
def VscrollBarMove(event):  # callback function
    but1.place(relx = rx, rely=ry+vBar.get()[0])
    but2.place(rely = ry2 + vBar.get()[0])  # You can set the only desirable coordinate if You want