tkinter frame问题

怎么才能在frame里面再设置一个frame,为外面的frame设置滚动条,让里面的frame可以随滚动条滚动显示?

tkinter不比win32 api的原生GUI,frame是没办法滚动的,只能使用canvas(推荐)或text作为父组件,里面加入一个Frame子控件。

下面是示例:

from tkinter import *
from tkinter import ttk
from ctypes import *

class ScrolledFrame(Canvas):

    def __init__(self,master,**kw):
        self.frame = Frame(master)
        self.vbar = Scrollbar(self.frame)
        self.vbar.pack(side=RIGHT, fill=Y)
        ###
        kw.update({'yscrollcommand': self.vbar.set})
        Canvas.__init__(self,self.frame,**kw)
        self.pack(fill=BOTH, expand=True)
        self.vbar['command'] = self.yview
        ###
        self.hbar=Scrollbar(self.frame,orient='horizontal',command=self.xview)
        self.hbar.pack(side=BOTTOM,fill=X)
        self.config(xscrollcommand=self.hbar.set)
        # Copy geometry methods
        canvas_meths = vars(Canvas).keys()
        methods = vars(Pack).keys() | vars(Grid).keys() | vars(Place).keys()
        methods = methods.difference(canvas_meths)
        for m in methods:
            if m[0] != '_' and m != 'config' and m != 'configure':
                setattr(self, m, getattr(self.frame, m))

    def add_frame(self,x=0,y=0,width=300,height=300,**kw):
        frame=Frame(self,**kw)
        self.create_window((x,y),width=width,height=height,window=frame,anchor='nw')
        self.configure(scrollregion=self.bbox('all'))
        return frame

r=Tk()
r.geometry('500x500')
sf=ScrolledFrame(r,bg='black')
sf.pack(fill='both',expand=True)

frame1=sf.add_frame()
ttk.Button(frame1,text='frame1 button').pack()

frame2=sf.add_frame(x=400,y=160)
ttk.Label(frame2,text='frame2 label').pack()

r.mainloop()