【问题标题】:Python, Tkinter: Calculating days left with tkcalendarPython,Tkinter:使用 tkcalendar 计算剩余天数
【发布时间】:2021-08-12 14:27:35
【问题描述】:

我有两个问题。

一个:

我不知道如何计算距离用户在日历界面中输入的特定日期的剩余天数。

其次:

我想使用用户在界面中输入的数字进行一些计算,并观察正在发生的事情,我将一些输入打印到终端 - 但是,.value 属性返回“0 "我不明白为什么。

在代码中的#PROXIMITY 注释下方,您可以找到日历/日期。我只想在日历界面中用户指定的日期减去今天的日期,输出剩下的天数。

#VALUE 下方是当我打印.value 属性时打印“0”的计算。

完整代码:

from tkcalendar import * # Calendar module
import tkinter.messagebox # Import the messagebox module
import datetime
import pickle


task_list = []
task_types = ['Sparetime', 'School', 'Work']

class Task:
    def __init__(self, n, type_, i, m, p, h, v): #(w=8, p, u, n, v):
        self.name = n
        self.type = type_
        self.impact = i
        self.manageability = m
        self.proximity = p
        self.hours = h
        self.value = v
        #self.connectivity = c
        ##self.work = w ##hours of work per day
        ##self.urgency = u
        ##self.note = n
        ##self.value = v



def show_tasks():
    # DELETED: for task in task_list:
    # REPLACED WITH: task = task_list[-1]
    task = task_list[-1]
    #print(
        #'Task:'+task.name + '\n' +
        #'Impact:' + task.impact + '\n' +
        #'Manageability:' + task.manageability + '\n' +
        #'Hours:' + task.hours + '\n'
        #'Value:' + task.value +'\n'
        #)
    print('Task:')
    print(task.name)
    print('\n')
    print('Impact:')
    print(task.impact)
    print('\n')
    print('manageability:')
    print(task.manageability)
    print('\n')
    print('Hours')
    print(task.hours)
    print('\n')
    print('Value:')
    print(task.value)

def open_add_task():
    taskwin = Toplevel(root)
    taskwin.focus_force()
    
    #TITLE
    titlelabel = Label(taskwin, text='Title task concisely:', font=('Roboto',11,'bold')).grid(column=1, row=0)
    name_entry = Entry(taskwin, width=40, justify='center')
    name_entry.grid(column=1, row=1)

    #TYPE
    typelabel = Label(taskwin, text='Type', font=('Roboto',10)).grid(column=0, row=2)
    type_var = StringVar(value=task_types[0])
    OptionMenu(taskwin, type_var, *task_types).grid(column=0, row=3, sticky='nsew')

    #IMPACT
    impactlabel = Label(taskwin, text='Impact', font=('Roboto',10)).grid(column=1, row=2)
    imp_var = StringVar(value=0)
    OptionMenu(taskwin, imp_var, *range(0, 10+1)).grid(column=1, row=3, sticky='ns')

    #MANAGEABILITY
    manlabel = Label(taskwin, text='Manageability', font=('Roboto',10)).grid(column=2, row=2)
    man_var = StringVar(value=0)
    OptionMenu(taskwin, man_var, *range(0, 10+1)).grid(column=2, row=3, sticky='nsew')



    #PROXIMITY
    proximity_label = Label(taskwin, text = 'Choose a deadline', font=('Roboto',10), justify='center')
    proximity_label.grid(column=1, row=4)
    cal = Calendar(taskwin, selectmode='day', year=2021, month=4, day=27)
    cal.grid(column=1, row=5)
    def get_date():
        proximity_output_date.config(text=cal.get_date()) ##the .config didn't work until i did .grid(column=, row=) on seperate lines

    
        



    #HOURS(required)
    hourlabel = Label(taskwin, text='Whole hours \n required', font=('Roboto',10)).grid(column=1, row=16)
    hour_entry = Entry(taskwin, width=4, justify='center')
    hour_entry.grid(column=1, row=17)

    #CONNECTIVITY
    #for index, task in enumerate(task_list):
    #Checkbutton(taskwin, **options).grid(column=0, row=index)
    C_lab = Label(taskwin,text="Check tasks this task is related to").grid(column=1, row=18)
    placement=19
    for task in task_list:
        Checkbutton(taskwin, text=(task.name)).grid(column=1, row=placement, sticky="w")
        placement+=1

    

    #VALUE
    val_var = (int(imp_var.get()))+ (int(man_var.get()))
        
    def add_task():
        if name_entry.get() != '': # If textbox inputfield is NOT empty do this:
            task_list.append(Task(name_entry.get(), type_var.get(), imp_var.get(), man_var.get(), cal.get_date(), hour_entry.get(), val_var))
            show_tasks()
            listbox_tasks.insert(tkinter.END, name_entry.get())
            name_entry.delete(0, tkinter.END)
            taskwin.destroy()
        else:
            tkinter.messagebox.showwarning(title='Whoops', message='You must enter a task')

        
    next_button = Button(taskwin, text='Next', font=('Roboto',10), command=add_task).grid(column=2, row=placement, sticky="e")
    placement+=1
    
def sort_tasks():
    pass
def delete_task():
    try:
        task_index = listbox_tasks.curselection()[0]
        listbox_tasks.delete(task_index)
    except:
        tkinter.messagebox.showwarning(title='Error', message='You must select a task to delete')

def save_tasks():
    pass
    #tasks = listbox_tasks.get(0, listbox_tasks.size())
    #pickle.dump(tasks, open('tasks.dat', 'wb'))
    


    
    
    
    

root = Tk()








task_frame = Frame()
# Create UI
your_tasks_label = Label(root, text='THESE ARE YOUR TASKS:', font=('Roboto',10, 'bold'), justify='center')
your_tasks_label.pack()


scrollbar_tasks = tkinter.Scrollbar(root)
scrollbar_tasks.pack(side=tkinter.RIGHT, fill=tkinter.Y)

listbox_tasks = tkinter.Listbox(root, height=10, width=50, font=('Roboto',10), justify='center') # tkinter.Listbox(where it should go, height=x, width=xx)
listbox_tasks.pack()

listbox_tasks.config(yscrollcommand=scrollbar_tasks.set)
scrollbar_tasks.config(command=listbox_tasks.yview)

try:
    #tasks = pickle.load(open('tasks.dat', 'rb'))
    listbox_tasks.delete(0, tkinter.END)
    for task in task_list:
        listbox_tasks.insert(tkinter.END, task)
except:
    tkinter.messagebox.showwarning(title='Phew', message='You have no tasks')

#BUTTONS
Add_Button = Button(root, text='Add New', width=42, command=open_add_task)
Add_Button.pack()

button_delete_task = Button(root, text='Delete task', width=42, command=delete_task)
button_delete_task.pack()


button_save_tasks = Button(root, text='Save tasks', width=42, command=save_tasks)
button_save_tasks.pack()

#sort_type = StringVar(value='All')
#OptionMenu(btn_frame, sort_type, 'All', *task_types).grid(column=0, row=0, sticky='nsew')

#sort_imp = StringVar(value='Any')
#OptionMenu(btn_frame, sort_imp,'Any', *range(0, 10+1)).grid(column=1, row=0, sticky='nsew')

#Button(btn_frame, text='Sort', command=sort_tasks).grid(column=1, row=1, sticky='nsew')
root.mainloop()

【问题讨论】:

    标签: python class object tkinter


    【解决方案1】:

    对于您的第一个问题,您可以使用cal.selection_get()datetime.date 类型返回所选日期。然后您可以轻松计算剩余天数:

    selected = cal.selection_get()
    delta = (selected - datetime.date.today()).days
    status = "overdue" if delta <= 0 else f"{delta} days left"
    print(f"{selected} ({status})")
    

    对于第二个问题,您需要将行 val_var = (int(imp_var.get()))+ (int(man_var.get())) 移动到 add_task() 函数中:

    def add_task():
        if name_entry.get() != '':
            val_var = int(imp_var.get()) + int(man_var.get())
            ...
        else:
            ...
    

    请注意,您需要对imp_var.get()man_var.get() 返回的值进行一些验证,以避免因无效值而导致异常。

    【讨论】:

    • 感谢您的帮助 - 非常感谢! cal.selection_get() 返回此行中指定的日期:cal = Calendar(taskwin, selectmode='day', year=2021, month=4, day=27) 现在让我有点沮丧。另外,为什么我必须将 val_var 行移动到 def add_task(): 中 - 我不遵循这一点,因为同一函数中还有其他东西是在函数之外定义的,它们似乎可以工作?
    • 您得到 0,因为该行在函数之外,并且在该行执行时,用户尚未更改值。进入函数,以便在用户更改值并单击Next 按钮后执行。
    • cal.selection_get() 应在您在日历上选择所需日期并需要计算剩余天数时调用。
    • 但实际上 - 很抱歉我是一个讨厌的菜鸟,对此了解很浅 - 但是 imp_varman_var 仍然在函数之外,但是当它们被调用时似乎仍然是用户输入的值。感觉我在这里完全错过了一些东西
    • 虽然这两个变量是在函数外部创建的,但它们的当前值只能在任何时候通过调用它们的.get() 函数来检索。在add_task() 内部是执行此操作的正确位置,而不是在它们刚刚创建之后。您需要了解事件驱动编程。
    【解决方案2】:

    如何计算距离特定日期的剩余天数

    您可以从datetime.date 中减去datetime.date 以得到datetime.timedelta 对象持有天数,请考虑以下示例

    import datetime
    d1 = datetime.date(2021, 1, 1)  # year, month, day
    d2 = datetime.date(2021, 1, 10)
    diff21 = (d2-d1).days
    diff12 = (d1-d2).days
    print(diff21)
    print(diff12)
    

    输出

    9
    -9
    

    要获取当前日期,您可以使用datetime.date.today()

    【讨论】:

    • 谢谢 - 我已经检查过了,问题(至少我认为是这样)是 tkcalendar 是“year/month/day”的形式,并且datetime 是“year-month-day”的形式,我需要 tkcalendar,因为用户必须在界面中选择一个日期。
    猜你喜欢
    • 2014-06-11
    • 2021-06-11
    • 2013-06-26
    • 1970-01-01
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多