使用 Tkinter 滚动和正确缩放

Scrolling and correct scaling with Tkinter

我需要这个简单的表格来: 1) 调整 window 大小时正确扩展字段和 2) 正确滚动字段列表。

我已经尝试了所有我能想到的方法,但上述 2 个条件中只有 1 个是正确的。此代码可以正确展开但不会滚动。没有 frame2,并将字段添加到 frame 或 canvas 则相反。

class test(Tkinter.Tk):

    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def makeform(self, root, fields):
        i = 0
        for field in fields:
            Label(root, text=field + ": ", anchor=W).grid(row=i)
            entry = Entry(root)
            entry.grid(row=i, column=1, sticky=E+W)
            entries[field] = entry
            i += 1

    def initialize(self):

        frame = Frame(self)
        frame.rowconfigure(0, weight=1)
        frame.columnconfigure(0, weight=1)
        frame.grid(sticky=N+S+E+W)

        canvas = Canvas(frame, width=900, height=800, bg='pink')
        canvas.grid(row=0, column=0, sticky=N+S+E+W)
        canvas.columnconfigure(0,weight=1)
        canvas.rowconfigure(0,weight=1)

        frame2 = Frame(canvas)
        frame2.grid(row=0, column=0, sticky=N+S+E+W)
        frame2.columnconfigure(1, weight=1)

        vscrollbar = Scrollbar(frame2,orient=VERTICAL)
        vscrollbar.grid(row=0, column=2, sticky=N+S)

        vscrollbar.config(command=canvas.yview)

        canvas.configure(yscrollcommand=vscrollbar.set)

        self.grid_rowconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        names = {'a','long','list','of','names','here'}
        self.makeform(frame2, names)

        Button(self, text='Quit', command=self.quit).grid(row=1, column=0, sticky=W, pady=4)

        canvas.create_window(0, 0)
        canvas.config(scrollregion=canvas.bbox(ALL))

        self.grid()

if __name__ == "__main__":

    entries = {}

    app = test(None)
    app.title('Hi ')
    app.mainloop()

更新

整合下面的 Bryan 示例,这适用于滚动,但在 window 调整大小时不会扩展字段。我尝试将 weight=1 添加到框架的第二列,但没有帮助。如何防止边框缩小?

class test(Tkinter.Frame):

    def __init__(self,parent):
        Tkinter.Frame.__init__(self, root)
        self.canvas = Tkinter.Canvas(root, borderwidth=0, background="#ffffff")
        self.frame = Tkinter.Frame(self.canvas, background="#ffffff")
        self.vsb = Tkinter.Scrollbar(root, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")
        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas.create_window((0,0), window=self.frame, anchor="nw",
                                  tags="self.frame")

        self.frame.bind("<Configure>", self.onFrameConfigure)

        self.populate()

    def onFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

    def makeform(self, fields):
        i = 0
        for field in fields:
            Label(self.frame, text=field + ": ", anchor=W).grid(row=i)
            entry = Entry(self.frame)
            entry.grid(row=i, column=1, sticky=E+W)
            entries[field] = entry
            i += 1
        Button(self.frame, text='Quit', command=self.quit).grid(row=i, column=0, sticky=W, pady=4)


    def populate(self):
        names = {'a','long','list','of','names','here'}
        self.makeform(names)
        self.frame.columnconfigure(1, weight=1)
        self.frame.grid_columnconfigure(1, weight=1)

if __name__ == "__main__":

    entries = {}

    root=Tk()
    test(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

您的代码中至少存在三个问题。

首先,要滚动的框架必须是 canvas 的一部分。不能用packgrid放在canvas里,必须用create_window。您正在调用 create_window,但没有告诉它要添加什么 window。

其次,滚动条是框架的子项,但我假设这些是您想要滚动 canvas 的滚动条。需要在inner frame之外,在canvas.

之外

第三,您需要设置到 canvas 的 <Configure> 事件的绑定,以便您可以调整内部框架的大小并重新计算 canvas 的滚动区域。

可滚动框架的完整工作示例在这个答案中: