I have two questions related to this attached code. This code is a part of my project in which i have to manage the attendance of 50 (or more) students.
When you will run this piece of code, you will see that there is a extra white space (that might be of the canvas) inside the Label Frame ie Attendance_Frame. All I wanted is that the there should be no extra white space and the scrollbar, instead of being at the extreme right, should be at the place where the labels end. I have searched for the answer to my question and saw a similar case. But there, the person wanted the frame to expand to the canvas size. Link ( Tkinter: How to get frame in canvas window to expand to the size of the canvas? ). But in my case, I want the canvas size to be equal to frame size (although the frame lies inside the canvas)
The other thing I want is that all the check boxes should initially be 'checked' (showing the present state) and when I uncheck random checkboxes (to mark the absent), and click the 'Submit' button (yet to be created at the bottom of the window), I should get a list with 'entered date' as first element and the roll numbers ie 2018-MC-XX as other elements. For example: ['01/08/2020', '2018-MC-7', '2018-MC-11', '2018-MC-23', '2018-MC-44']. Actually my plan is when i will get a list i will easily write it to a text file.
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()
If you are creating a vertical list of items, you don't need to use a frame inside the canvas. The inner frame adds some unnecessary complexity. Instead, create the checkbuttons directly on the canvas with create_window
.
You also need to configure the scrollregion
attribute so that the scrollbar knows how much of the virtual canvas to scroll.
Finally, to have them selected you should assign a variable to each checkbutton, and make sure that the value is the proper value. By default checkbuttons use the values 0 and 1, so setting the variable to 1 will make it selected.
vars = []
for i in range(0,51):
var = IntVar(value=1)
vars.append(var)
x0, y0, x1, y1 = canvas.bbox("all") or (0,0,0,0)
c = Checkbutton(canvas, text = f"{'2018-MC-'+str(i+1)} Student {i+1}", variable=var)
canvas.create_window(2, y1+4, anchor="nw", window=c)
canvas.configure(scrollregion=canvas.bbox("all"))
import tkinter as tk
from tkcalendar import DateEntry
root = tk.Tk()
root.geometry('920x600+270+50')
root.minsize(960, 600)
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
Attendance_frame = tk.Frame(root)
Attendance_frame.grid(row=0, column=0, sticky='nsew')
attendaceBox = tk.LabelFrame(Attendance_frame,
text='Take Attendance',
bd=4,
relief='groove',
labelanchor='n',
font='Arial 10 bold',
fg='navy blue',
width=850,
height=525)
attendaceBox.grid(row=0, column=0, sticky='nsew', padx=15)
Attendance_frame.columnconfigure(0, weight=1)
Attendance_frame.rowconfigure(0,weight=1)
dateFrame = tk.Frame(attendaceBox) # A small frame to accommodate date entry label & entry box
dateFrame.grid(row=0, column=0, sticky='nsew')
font = 'TkDefaultFont 10 bold'
date_label = tk.Label(dateFrame, text='Enter Date : ', font=font)
date_label.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 = tk.Label(attendaceBox, text='Note: Uncheck the boxes for absentees', anchor='w')
noteLabel.grid(row=1, column=0, sticky='nsew')
attendaceBox.rowconfigure(2, weight=1)
canvas = tk.Canvas(attendaceBox, width=200, borderwidth=0, background="#ffffff")
# You can set width of canvas according to your need
canvas.grid(row=2, column=0, sticky='nsew')
canvas.columnconfigure(0, weight=1)
canvas.rowconfigure(0, weight=1)
vsb = tk.Scrollbar(attendaceBox, orient="vertical", command=canvas.yview)
vsb.grid(row=2, column=1, sticky='nsew')
canvas.configure(yscrollcommand=vsb.set)
checkFrame = tk.Frame(canvas, bg='green')
canvas.create_window((0, 0), window=checkFrame, anchor="nw", tags='expand')
checkFrame.columnconfigure(0, weight=1)
for i in range(0, 51): # A loop to create Labels of students roll numbers & names
c = tk.Checkbutton(checkFrame, anchor='w', text=f"{'2018-MC-' + str(i + 1)} Student {i + 1}")
c.grid(row=i, column=0, sticky='nsew')
c.select()
canvas.bind('<Configure>', lambda event: canvas.itemconfigure('expand', width=event.width))
checkFrame.update_idletasks()
canvas.config(scrollregion=canvas.bbox('all'))
root.mainloop()
Get Selected Value
vars = []
for i in range(0, 51): # A loop to create Labels of students roll numbers & names
var = tk.IntVar()
c = tk.Checkbutton(checkFrame,
variable=var,
anchor='w', text=f"{'2018-MC-' + str(i + 1)} Student {i + 1}")
c.grid(row=i, column=0, sticky='nsew')
c.select()
vars.append(var)
def state():
print(list(map((lambda var: var.get()), vars)))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.