[英]Resizing the Canvas equal to the frame size in tkinter python
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.
这段代码是我项目的一部分,我必须管理 50 名(或更多)学生的出勤率。
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.当您运行这段代码时,您会看到 Label Frame 即 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.
但是在那里,该人希望框架扩展到 canvas 尺寸。 Link ( Tkinter: How to get frame in canvas window to expand to the size of the canvas? ).
链接( Tkinter: How to get frame in canvas window to expand to the size of the ZFCC790C72A86190DE1B549DC )。 But in my case, I want the canvas size to be equal to frame size (although the frame lies inside the canvas)
但就我而言,我希望 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.我想要的另一件事是所有复选框最初都应该被“选中”(显示当前状态),当我取消选中随机复选框(以标记不存在)时,然后单击“提交”按钮(尚未在窗口底部),我应该得到一个列表,其中“输入日期”作为第一个元素,卷号即 2018-MC-XX 作为其他元素。 For example: ['01/08/2020', '2018-MC-7', '2018-MC-11', '2018-MC-23', '2018-MC-44'].
例如:['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.如果要创建项目的垂直列表,则不需要在 canvas 内使用框架。 The inner frame adds some unnecessary complexity.
内部框架增加了一些不必要的复杂性。 Instead, create the checkbuttons directly on the canvas with
create_window
.相反,使用 create_window 直接在
create_window
上创建复选按钮。
You also need to configure the scrollregion
attribute so that the scrollbar knows how much of the virtual canvas to scroll.您还需要配置
scrollregion
属性,以便滚动条知道要滚动多少虚拟 canvas。
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.
默认情况下,检查按钮使用值 0 和 1,因此将变量设置为 1 将使其被选中。
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)))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.