首页 > 解决方案 > 带有 tkinter 的非常长的清单框

问题描述

我正在使用此答案中的代码制作带有复选框的列表。

import tkinter as tk

root = tk.Tk()

class ChecklistBox(tk.Frame):
    def __init__(self, parent, choices, **kwargs):
        tk.Frame.__init__(self, parent, **kwargs)
        
        self.vars = []
        bg = self.cget("background")
        for choice in choices:
            var = tk.StringVar(value=choice)
            self.vars.append(var)
            cb = tk.Checkbutton(self, var=var, text=choice,
                                onvalue=choice, offvalue="",
                                anchor="w", width=20, background=bg,
                                relief="flat", highlightthickness=0
            )
            cb.pack(side="top", fill="x", anchor="w")
    
    
    def getCheckedItems(self):
        values = []
        for var in self.vars:
            value =  var.get()
            if value:
                values.append(value)
        return values

choices = [str(e) for e in range(100)]
checklist = ChecklistBox(root, choices, bd=1, relief="sunken", background="white")
checklist.pack()

由于选项列表很长,我想在此列表中添加一个滚动条。做这个的最好方式是什么 ?


我尝试按照此处的示例进行操作,但ChecklistBox没有yview方法,也没有yscrollcommand选择。我不知道如何规避这个问题。

标签: pythonpython-3.xtkintercheckboxscrollbar

解决方案


问题的根源是框架不可滚动。因此,您必须找到一个支持滚动的小部件并将其用作向一组小部件添加滚动的基础。

Canvas部件通常用于此目的。它通常与内部框架一起使用,这使得它易于使用packgrid排列小部件。但是,因为您正在创建相同小部件的垂直堆栈,所以直接在画布上绘制复选按钮会更容易。

第一步是在框架中添加画布和滚动条:

class ChecklistBox(tk.Frame):
    def __init__(self, parent, choices, **kwargs):
        tk.Frame.__init__(self, parent, **kwargs)

        canvas = tk.Canvas(self, background=self.cget("background"))
        vsb = tk.Scrollbar(self, command=canvas.yview)
        canvas.configure(yscrollcommand=vsb.set)
        vsb.pack(side="right", fill="y")
        canvas.pack(side="left", fill="both", expand=True)
        ...

接下来,pack我们将调用create_window. 我们可以通过获取上一项的 y 坐标来确定下一项的放置位置。我们将使用pady框架的选项来进行间距。

        pady = int(str(self.cget("pady")))
        for choice in choices:
            ...
            bbox = canvas.bbox("all")
            y0 = pady if bbox is None else bbox[3]+pady
            canvas.create_window(0, y0, window=cb, anchor="nw")

最后,您需要确保scrollregion设置正确:

        canvas.configure(scrollregion=canvas.bbox("all"))

推荐阅读