以编程方式创建复选框,并使用tkinter获取其值

时间:2015-01-16 03:11:26

标签: python python-3.x tkinter

我在SO question中有一个修改后的答案版本,但主要结构保持不变。我想知道如何在该字典中添加复选框,然后迭代复选框的值? tkinter中的复选框需要一个我最终会检查的变量,因此我不确定如何使用此方法创建变量。

如何在上面提到的问题答案的每一行末尾创建复选框?

我尝试了以下(最后2行):

            self.widgets[rowid] = {
                "rowid": ttk.Label(table, text=rowid, width=20, anchor=CENTER, relief=SUNKEN),
                "reviewer": ttk.Label(table, text=reviewer, width=20, anchor=CENTER, relief=SUNKEN),
                "task": ttk.Label(table, text=task, width=20, anchor=CENTER, relief=SUNKEN),
                "num_seconds_correction": ttk.Entry(table),
                "num_seconds": ttk.Label(table, text=num_seconds, width=20, anchor=CENTER, relief=SUNKEN),
                "start_time": ttk.Label(table, text=start_time, width=20, anchor=CENTER, relief=SUNKEN),
                "end_time": ttk.Label(table, text=start_time, width=20, anchor=CENTER, relief=SUNKEN),
                "checkbox_var": IntVar(),
                "checkbox": ttk.Checkbutton(table)
            }

在小部件放置在网格中的部分,我尝试将变量分配给复选框,然后将其放在网格上(最后2行):

#this just puts everything in the grid in the right place
self.widgets[rowid]["rowid"].grid(row=row, column=0, sticky="nsew")
self.widgets[rowid]["reviewer"].grid(row=row, column=1, sticky="nsew")
self.widgets[rowid]["task"].grid(row=row, column=2, sticky="nsew")
self.widgets[rowid]["num_seconds_correction"].grid(row=row, column=3, sticky="nsew")
self.widgets[rowid]["num_seconds"].grid(row=row, column=4, sticky="nsew")
self.widgets[rowid]["start_time"].grid(row=row, column=5, sticky="nsew")
self.widgets[rowid]["end_time"].grid(row=row, column=6, sticky="nsew")

self.widgets[rowid]["checkbox"].config(variable=(self.widgets[rowid]["checkbox_var"]))
self.widgets[rowid]["checkbox"].grid(row=row, column=7, sticky="nsew")

这使得复选框显示在正确的位置。然后,当我遍历值以查看检查了哪些框时,即使选中了其中一​​些框,也会为所有框返回0:

for rowid in sorted(self.widgets.keys()):
    check_widget = self.widgets[rowid]["checkbox"]
    delete_value = check_widget.get()
    print(delete_value)

即使选中了复选框,此迭代也只返回0。我在这里做错了什么?它与将变量分配给复选框有关吗?

然后我尝试了一些不同的东西:

self.check = IntVar()
self.widgets[rowid] = {
    "rowid": ttk.Label(table, text=rowid, width=20, anchor=CENTER, relief=SUNKEN),
    "reviewer": ttk.Label(table, text=reviewer, width=20, anchor=CENTER, relief=SUNKEN),
    "task": ttk.Label(table, text=task, width=20, anchor=CENTER, relief=SUNKEN),
    "num_seconds_correction": ttk.Entry(table),
    "num_seconds": ttk.Label(table, text=num_seconds, width=20, anchor=CENTER, relief=SUNKEN),
    "start_time": ttk.Label(table, text=start_time, width=20, anchor=CENTER, relief=SUNKEN),
    "end_time": ttk.Label(table, text=start_time, width=20, anchor=CENTER, relief=SUNKEN),
    "checkbox": ttk.Checkbutton(table, variable=self.check)
}

然后迭代它:

for rowid in sorted(self.widgets.keys()):
    print(self.check.get())

但它只打印0,任何想法?

修改 这是班级的整个实际状态:

class Example(ttk.Frame):
    def __init__(self, parent):
        ttk.Frame.__init__(self, parent)
        b = ttk.Button(self, text="Done!", command=self.upload_cor) #submit button
        b.pack()
        b2 = ttk.Button(self, text="Close", command=self.destroy_cor) #close button
        b2.pack(side="right")
        table = ttk.Frame(self)
        table.pack(side="top", fill="both", expand=True)

        data = results #results is the nested list with the query results of rows for one day

        self.widgets = {}
        row = 0
        total=0 #this will keep track of the total of hours for that day

        #this iteration creates all the labels and positions them
        for rowid, reviewer, task, num_seconds, start_time, end_time in (data):
            row += 1

            self.check = BooleanVar()
            #this is a dictionary, this makes it easier keep track of the values inside
            #text boxes when they're changed
            self.widgets[rowid] = {
                "rowid": ttk.Label(table, text=rowid, width=20, anchor=CENTER, relief=SUNKEN),
                "reviewer": ttk.Label(table, text=reviewer, width=20, anchor=CENTER, relief=SUNKEN),
                "task": ttk.Label(table, text=task, width=20, anchor=CENTER, relief=SUNKEN),
                "num_seconds_correction": ttk.Entry(table),
                "num_seconds": ttk.Label(table, text=num_seconds, width=20, anchor=CENTER, relief=SUNKEN),
                "start_time": ttk.Label(table, text=start_time, width=20, anchor=CENTER, relief=SUNKEN),
                "end_time": ttk.Label(table, text=start_time, width=20, anchor=CENTER, relief=SUNKEN),

                "checkbox": ttk.Checkbutton(table, variable=self.check)
            }

            total = total + int(num_seconds)

            #this just puts everything in the grid in the right place
            self.widgets[rowid]["rowid"].grid(row=row, column=0, sticky="nsew")
            self.widgets[rowid]["reviewer"].grid(row=row, column=1, sticky="nsew")
            self.widgets[rowid]["task"].grid(row=row, column=2, sticky="nsew")
            self.widgets[rowid]["num_seconds_correction"].grid(row=row, column=3, sticky="nsew")
            self.widgets[rowid]["num_seconds"].grid(row=row, column=4, sticky="nsew")
            self.widgets[rowid]["start_time"].grid(row=row, column=5, sticky="nsew")
            self.widgets[rowid]["end_time"].grid(row=row, column=6, sticky="nsew")

            #self.widgets[rowid]["checkbox"].config(variable=(self.widgets[rowid]["checkbox_var"]))
            self.widgets[rowid]["checkbox"].grid(row=row, column=7, sticky="nsew")

        ttk.Label(table, text='Total:',width=20, anchor=E, relief=SUNKEN).grid(row=row+1, column=3)    #this 2 display the total hours
        ttk.Label(table, text=total, width=20, anchor=CENTER, relief=SUNKEN).grid(row=row+1, column=4) #spent on the selected day

        table.grid_columnconfigure(1, weight=1)
        table.grid_columnconfigure(2, weight=1)

        # invisible row after last row gets all extra space
        table.grid_rowconfigure(row+1, weight=1)

    globals().update(locals())

    #########################
    #uploads the new values if they
    #were changed
    def upload_cor(self):

        globals().update(locals())


        for rowid in sorted(self.widgets.keys()):

            print(self.check)

            #here is where I need something to see if the boxes are checked  

1 个答案:

答案 0 :(得分:1)

我修改了添加了您添加的位的示例中的代码。这是完整的代码:

import tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        b = tk.Button(self, text="Done!", command=self.upload_cor)
        b.pack()
        table = tk.Frame(self)
        table.pack(side="top", fill="both", expand=True)

        data = (
            (45417, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"),
            (45418, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"),
            (45419, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"),
            (45420, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"),
            (45421, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"),
            (45422, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"),
            (45423, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 10:08:12", "2014-12-19 10:08:12"),
        )

        self.widgets = {}
        row = 0
        for rowid, reviewer, task, num_seconds, start_time, end_time in (data):
            row += 1
            self.widgets[rowid] = {
                "rowid": tk.Label(table, text=rowid),
                "reviewer": tk.Label(table, text=reviewer),
                "task": tk.Label(table, text=task),
                "num_seconds_correction": tk.Entry(table),
                "num_seconds": tk.Label(table, text=num_seconds),
                "start_time": tk.Label(table, text=start_time),
                "end_time": tk.Label(table, text=start_time),
                "checkbox_var": tk.IntVar(),
                "checkbox": tk.Checkbutton(table)
            }

            self.widgets[rowid]["rowid"].grid(row=row, column=0, sticky="nsew")
            self.widgets[rowid]["reviewer"].grid(row=row, column=1, sticky="nsew")
            self.widgets[rowid]["task"].grid(row=row, column=2, sticky="nsew")
            self.widgets[rowid]["num_seconds_correction"].grid(row=row, column=3, sticky="nsew")
            self.widgets[rowid]["num_seconds"].grid(row=row, column=4, sticky="nsew")
            self.widgets[rowid]["start_time"].grid(row=row, column=5, sticky="nsew")
            self.widgets[rowid]["end_time"].grid(row=row, column=6, sticky="nsew")

            self.widgets[rowid]["checkbox"].config(variable=(self.widgets[rowid]["checkbox_var"]))
            self.widgets[rowid]["checkbox"].grid(row=row, column=7, sticky="nsew")

        table.grid_columnconfigure(1, weight=1)
        table.grid_columnconfigure(2, weight=1)
        # invisible row after last row gets all extra space
        table.grid_rowconfigure(row+1, weight=1)

    def upload_cor(self):
        for rowid in sorted(self.widgets.keys()):
            entry_widget = self.widgets[rowid]["num_seconds_correction"]
            new_value = entry_widget.get()
            print("%s: %s" % (rowid, new_value))

        for rowid in sorted(self.widgets.keys()):
            check_var = self.widgets[rowid]["checkbox_var"]
            print(check_var.get())
            if check_var.get():
                print('Check button checked')



if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()

具体来看看upload_cor。正如您所看到的,我想要获取复选框变量而不是check_widget = self.widgets[rowid]["checkbox"]。我认为这是你的代码的问题。您获取窗口小部件,而不是与窗口小部件关联的变量。希望它有所帮助。