动态在可滚动框架中添加复选框

1 投票
1 回答
4926 浏览
提问于 2025-04-18 05:29

我知道这里有很多类似的问题,但我找到的这些都不适合我。情况是这样的:

我需要在一个框架里动态加载复选框,但我不知道会有多少个复选框。所以我需要一个滚动条。我听说在框架里放滚动条是不行的,除非把框架放到一个画布里,然后把滚动条加到画布上。我觉得问题可能和滚动区域有关,但我不太确定。

这是我代码的相关部分:

def checkboxes_container(self):
    # Checkboxes frame
    self.checkboxes_frame = \
        tk.Frame(self,
                 height=450,
                 bg='red', bd=0,
                 highlightthickness=0)
    # Canvas widget to add scroll to the checkboxes holder
    self.canvas = \
        tk.Canvas(self.checkboxes_frame,
                  bg='blue', bd=0,
                  highlightthickness=0)
    # Canvas sizer
    canvas_sizer = tk.Frame(self.canvas, height=350,
                            bg='#444444', bd=0,
                            highlightthickness=0)
    canvas_sizer.pack(side=tk.LEFT)
    # Checkboxes holder
    self.checkbox_pane = \
        tk.Frame(self.canvas,
                 bg='#444444', bd=0,
                 highlightthickness=0)
    self.checkbox_pane.grid_propagate(False)
    # Scrollbar for checkbox pane
    self.scrollbar = tk.Scrollbar(self.checkboxes_frame,
                                  bg='grey', bd=0,
                                  activebackground='#A3A3A3',
                                  troughcolor='#444444',
                                  width=16,
                                  orient=tk.VERTICAL)

    self.canvas.create_window(0, 0, window=self.checkbox_pane)
    # Grid holder
    self.checkboxes_frame.grid(row=1, column=0, sticky=tk.W+tk.E)
    # Grid widgets to the holder
    self.canvas.pack(expand=True, side=tk.LEFT, fill=tk.BOTH)
    self.checkbox_pane.pack(expand=True, fill=tk.BOTH)
    self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

    self.scrollbar.config(command=self.canvas.yview)
    self.canvas.config(yscrollcommand=self.scrollbar.set,
                       scrollregion=
                       self.canvas.bbox('all'))

self是我的基本框架小部件,我在里面放其他小部件的容器(就像这个)。

如果有人能帮我,我会非常感激。我今天一直在尝试这个……我一定很接近成功了……或者我很笨。

提前谢谢你们!祝好!

编辑:添加了修改后的代码:

class ScrollableFrame(tk.Frame):
    def __init__(self, master, **kwargs):
        tk.Frame.__init__(self, master, kwargs)

        # create a canvas object and a vertical scrollbar for scrolling it
        self.vscrollbar = tk.Scrollbar(self, orient=tk.VERTICAL)
        self.vscrollbar.pack(side='right', fill="y",  expand="false")
        self.canvas = tk.Canvas(self,
                                bg='#444444', bd=0,
                                height=350,
                                highlightthickness=0,
                                yscrollcommand=self.vscrollbar.set)
        self.canvas.pack(side="left", fill="both", expand="true")
        self.vscrollbar.config(command=self.canvas.yview)

        # reset the view
        self.canvas.xview_moveto(0)
        self.canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = tk.Frame(self.canvas, kwargs)
        self.canvas.create_window(0, 0, window=self.interior, anchor="nw")


class Application(tk.Frame):
    # ...

    def checkboxes_container(self):
        self.checkbox_pane = ScrollableFrame(self,
                                             bg='#444444')
        self.checkbox_pane.grid(row=1, column=0,
                                columnspan=3,
                                sticky='nwes')

1 个回答

3

创建一个类然后调用它,可能比直接使用 Tkinter.Frame 更简单。

注意,有一个叫做 interior 的实例变量,你需要用它来在滚动框架里面显示小部件。

import Tkinter as tk

class ScrollableFrame(tk.Frame):
    def __init__(self, master, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)

        # create a canvas object and a vertical scrollbar for scrolling it
        self.vscrollbar = tk.Scrollbar(self, orient=tk.VERTICAL)
        self.vscrollbar.pack(side='right', fill="y",  expand="false")
        self.canvas = tk.Canvas(self,
                                bg='#444444', bd=0,
                                height=350,
                                highlightthickness=0,
                                yscrollcommand=self.vscrollbar.set)
        self.canvas.pack(side="left", fill="both", expand="true")
        self.vscrollbar.config(command=self.canvas.yview)

        # reset the view
        self.canvas.xview_moveto(0)
        self.canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = tk.Frame(self.canvas, **kwargs)
        self.canvas.create_window(0, 0, window=self.interior, anchor="nw")

        self.bind('<Configure>', self.set_scrollregion)


    def set_scrollregion(self, event=None):
        """ Set the scroll region on the canvas"""
        self.canvas.configure(scrollregion=self.canvas.bbox('all'))


if __name__ == '__main__':
    root = tk.Tk()
    checkbox_pane = ScrollableFrame(root, bg='#444444')
    checkbox_pane.pack(expand="true", fill="both")

    def button_callback():
        for x in range(1,20):
            tk.Checkbutton(checkbox_pane.interior, text="hello world! %s" % x).grid(row=x, column=0)

    btn_checkbox = tk.Button(checkbox_pane.interior, text="Click Me!", command=button_callback)
    btn_checkbox.grid(row=0, column=0)
    root.mainloop()

代码摘自 这里

撰写回答