使用 for 循环从 tkinter 复选框创建和获取值

Creating and Getting values from tkinter check boxes using for loop

此代码是我的项目的一部分,我必须在该项目中管理 50 名(或更多)学生的出勤率。

我想要的是所有复选框最初应该是 'checked' (显示当前状态) 当我取消选中随机复选框时 (标记不存在)然后点击Submit按钮(yet to be created at the bottom of the window),我应该得到一个以 'entered date' 作为第一个元素并以卷号(即 2018-MC-XX)作为其他元素的列表。

例如: ['01/08/2020', '2018-MC-7', '2018-MC-11', '2018-MC-23', '2018-MC-44']

实际上我的计划是当我得到一个列表时,我会很容易地将它写入一个文本文件。另外,如果有另一种方法可以创建多个可滚动复选框而不将它们打包在 canvas 中,那么请告诉我!

from tkinter import *
from tkcalendar import DateEntry

root = Tk()
root.geometry('920x600+270+50')
root.minsize(920,600)

Attendance_frame = Frame(root)    ### Consider it a Main Frame
Attendance_frame.pack()

attendaceBox = LabelFrame(Attendance_frame, text = 'Take Attendance', bd = 4, relief = GROOVE, labelanchor = 'n',font = 'Arial 10 bold', fg = 'navy blue', width = 850, height = 525)     # A Label Frame inside the main frame

attendaceBox.pack_propagate(0)
attendaceBox.pack(pady = 15)

dateFrame = Frame(attendaceBox)    # A small frame to accommodate date entry label & entry box
dateFrame.pack(anchor = 'w')

font = 'TkDefaultFont 10 bold'
date_label = Label(dateFrame, text = 'Enter Date : ', font = font).grid(row = 0, column =  0, sticky = 'w', padx = 10, pady = 10)

date_entry = DateEntry(dateFrame, date_pattern = 'dd/mm/yyyy', showweeknumbers = FALSE, showothermonthdays = FALSE)
date_entry.grid(row = 0, column = 1, sticky = 'w')

noteLabel = Label(attendaceBox, text = 'Note: Uncheck the boxes for absentees').pack(anchor = 'w', padx = 10, pady = 5)

canvas = Canvas(attendaceBox, borderwidth=0, background="#ffffff")
checkFrame = Frame(canvas, width = 100, height = 50)
vsb = Scrollbar(canvas, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)

vsb.pack(side="right", fill="y")
canvas.pack(side="left", fill="both", expand=True)
canvas.pack_propagate(0)
canvas.create_window((4,4), window=checkFrame, anchor="nw")

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

checkFrame.bind("<Configure>", lambda event, canvas=canvas: onFrameConfigure(canvas))

for i in range(0,51):     # A loop to create Labels of students roll numbers & names
    c = Checkbutton(checkFrame, text = f"{'2018-MC-'+str(i+1)}       Student {i+1}")
    c.grid(row = i, column = 0, padx = 10, sticky = 'w')


mainloop()

首先,每个 Checkbutton 都需要 StringVar,以便稍后获取 Checkbuttons 的状态。然后你可以使用一个列表来保存 StringVars 以便你以后可以访问它们。您可以将 checkbuttonsonvalue 设置为与其关联的卷号。

您也可以使用 Text 小部件代替 Canvas+Frame。下面是一个例子:

import tkinter as tk

root = tk.Tk()

frame = tk.Frame(root)
frame.pack()

text = tk.Text(frame, width=40, height=20)
text.pack(side=tk.LEFT, fill=tk.BOTH)

vars = []
for i in range(51):
    rollnum = '2018-MC-'+str(i+1)
    var = tk.StringVar(value=rollnum)
    cb = tk.Checkbutton(text, text=rollnum, variable=var, onvalue=rollnum, offvalue='', bg='white')
    text.window_create('end', window=cb)
    text.insert('end', '\n')
    vars.append(var)

vsb = tk.Scrollbar(frame, orient=tk.VERTICAL, command=text.yview)
vsb.pack(side=tk.RIGHT, fill=tk.Y)

text.config(yscrollcommand=vsb.set)

def submit():
    # extract roll numbers for checked checkbuttons
    result = [var.get() for var in vars if var.get()]
    print(result)

tk.Button(root, text='Submit', command=submit).pack()

root.mainloop()