-1

Being a student in the times of the coronavirus, schools are not open and therefore I must work at home, while still following a specific timetable. I have made a virtual planner using tkinter in python that tells me what lesson I have, how long left I have (using a progress bar) and what lesson I have next. This is what it looks like.

But when the lesson changes, the old lesson still remains, and the new one is just written over it. It then looks like this. RE (Religious education) is written above maths.

The code I have is this:

from tkinter import *
from datetime import datetime, date
from tkinter.ttk import Progressbar
from tkinter import ttk
import math
num = 0

window = Tk()
window.title("Planner")
monday = ['Maths', 'RE', 'Break', 'English', 'Spanish', 'Lunch', 'Music']
tuesday = ['Science', 'History', 'Break', 'Technology', 'Maths', 'Lunch', 'Geography']
wednesday = ['English', 'Games', 'Break', 'Drama', 'Computing', 'Lunch', 'Science']
thursday = ['Art', 'Geography', 'Break', 'Spanish', 'Computing', 'Lunch', 'English']
friday = ['PE', 'History', 'Break', 'Maths', 'Science', 'Lunch', 'English']
timing = [845, 945, 1045, 1100, 1200, 1300, 1350, 1450]

def update():
    global num
    global day
    global time
    now = datetime.now()
    hour = now.strftime("%H")
    minu = now.strftime("%M")
    day = now.strftime("%A")
    time = (hour+minu)
    if int(time) < 1449 and int(time) > 845:

        for i in timing:
            if int(time) < int(timing[num]):
                lesson_time = (timing[num-1])
                break
            num = num + 1
        num = num - 1

        if day == 'Monday':
            text = StringVar()
            label = Label(window, textvariable = text, font=("Arial Bold", 10), fg='darkblue')
            label.grid(row=1, column=0)
            text.set(monday[num])
            if num <= 5:
                next_up = Label(window, text = ("Next: " + monday[num+1]), font=("Arial Bold", 10), fg='darkblue')
                next_up.grid(row=1, column=1)

        elif day == 'Tuesday':
            text = StringVar()
            label = Label(window, textvariable = text, font=("Arial Bold", 10), fg='darkblue')
            label.grid(row=1, column=0)
            text.set(tuesday[num])
            if num <= 5:
                next_up = Label(window, text = ("   Next: "  +  tuesday[num+1] + '     '), font=("Arial Bold", 10), fg='darkblue')
                next_up.grid(row=1, column=1)

        elif day == 'Wednesday':
            text = StringVar()
            label = Label(window, textvariable = text, font=("Arial Bold", 10), fg='darkblue')
            label.grid(row=1, column=0)
            text.set(wednesday[num])
            if num <= 5:
                next_up = Label(window, text = ("Next: " + wednesday[num+1]), font=("Arial Bold", 10), fg='darkblue')
                next_up.grid(row=1, column=1)

        elif day == 'Thursday':
            text = StringVar()
            label = Label(window, textvariable = text, font=("Arial Bold", 10), fg='darkblue')
            label.grid(row=1, column=0)
            text.set(thursday[num])
            if num <= 5:
                next_up = Label(window, text = ("Next: " + thursday[num+1]), font=("Arial Bold", 10), fg='darkblue')
                next_up.grid(row=1, column=1)

        elif day == 'Friday':
            text = StringVar()
            label = Label(window, textvariable = text, font=("Arial Bold", 10), fg='darkblue')
            label.grid(row=1, column=0)
            text.set(friday[num])
            if num <= 5:
                next_up = Label(window, text = ("Next: " + friday[num+1]), font=("Arial Bold", 10), fg='darkblue')
                next_up.grid(row=1, column=1)

        else:
            no_school = Label(window, text = 'Relax - No School!', font=("Arial Bold", 10), fg='darkblue')
            no_school.grid(row=0, column=0)


        if day != 'Saturday' or 'Sunday':
            style = ttk.Style()
            style.theme_use('default')
            style.configure("black.Horizontal.TProgressbar", background='black')
            bar = Progressbar(window, length=100, style='black.Horizontal.TProgressbar', max=60)
            if num == 2:
                target = 15
            elif num == 5:
                target = 50
            else:
                target = 60

            diviser = 60/target
            difference = str(timing[num])[-2:]
            top = (int(timing[num+1])) - int(difference)
            bottom = (int(timing[num])) - int(difference)
            round_time = int(minu) - int(difference)
            if top < 0:
                top = top + 60

            if round_time < 0:
                round_time = round_time + 60
            bar['value'] = (round_time*diviser)
            bar.grid(column=1, row=0)

    else:
        if day == 'Saturday' or day == 'Sunday':
            no_school = Label(window, text = 'Relax - No school!',  font=("Arial Bold", 10), fg='darkblue')
            no_school .grid(row = 0, column = 0)

        else:
            no_school= Label(window, text = 'Relax - No School!',  font=("Arial Bold", 10), fg='darkblue')
            no_school.grid(row = 0, column = 0)


update()
if not day == 'Saturday' or 'Sunday':
    if not (int(time) > 1449) and not (int(time) < 844):
        update = Button(window, text='Update', command=update)
        update.grid(row=0, column = 3)


window.mainloop()

I tried label.destroy() before changing the label text (changing the subject). This did not produce an error message but just did not solve the problem.

Also, I have another problem. It is that I have to manually press 'update' so that it tells me the up-to-date information. Is there a way to have it update automatically? I tried putting update() in a for loop, but this did not work.

martineau
  • 119,623
  • 25
  • 170
  • 301
RAW_tech
  • 55
  • 1
  • 8
  • Please provide a [mre] (or describe how to do it with what's currently in your question). – martineau Mar 23 '20 at 19:15
  • 1
    First you have to understand [Event-driven programming](https://stackoverflow.com/a/9343402/7414759) – stovfl Mar 23 '20 at 19:41
  • You should not create new labels in each update. Create the UI (labels and progressbar) at program start, then just change the text of labels and the progress bar in each update. – acw1668 Mar 24 '20 at 02:11

1 Answers1

0

You should not create new labels in each update. Create the UI at program start, then just change the text of the labels and update the progress bar in each update. You can use .after(...) to repeat the update periodically.

Also redundant code for each weekday should be avoided.

Below is simplified code:

import tkinter as tk
from tkinter import ttk
from datetime import datetime

lessons = [
    ['Maths',   'RE',        'Break', 'English',    'Spanish',   'Lunch', 'Music'],     # Monday
    ['Science', 'History',   'Break', 'Technology', 'Maths',     'Lunch', 'Geography'], # Tuesday
    ['English', 'Games',     'Break', 'Drama',      'Computing', 'Lunch', 'Science'],   # Wednesday
    ['Art',     'Geography', 'Break', 'Spanish',    'Computing', 'Lunch', 'English'],   # Thursday
    ['PE',      'History',   'Break', 'Maths',      'Science',   'Lunch', 'English'],   # Friday
]
timing = [845, 945, 1045, 1100, 1200, 1300, 1350, 1450]
total_lessons = len(timing) - 1

def get_lesson(time):
    ''' get time slot of given time (HHMM) '''
    for i in range(len(timing)-1):
        if timing[i] <= time < timing[i+1]:
            return i
    return None

def time_diff(t1, t2):
    ''' calculate difference in minutes between two time (HHMM) '''
    h1, m1 = divmod(t1, 100)
    h2, m2 = divmod(t2, 100)
    h, m = h2-h1, m2-m1
    if m < 0:
        h -= 1
        m += 60
    return h*60 + m

def update():
    now = datetime.now()
    wday = now.weekday()  # get weekday, Monday is 0
    time = now.hour*100 + now.minute # get time in HHMM
    lesson = get_lesson(time)
    if wday in (5, 6) or lesson is None: # Sunday or Saturday or no lesson
        no_school.lift()
    else:
        cur_lesson.config(text=lessons[wday][lesson])
        next_lesson.config(text='Next: '+lessons[wday][lesson+1] if lesson+1 < total_lessons else '')
        # update progressbar
        target = time_diff(timing[lesson], timing[lesson+1]) * 60  # total seconds for current lesson
        seconds = time_diff(timing[lesson], time) * 60 + now.second  # seconds since lesson start
        progress = seconds * 100 // target  # percentage of progress
        progressbar.config(value=progress)
        school.lift()
    window.after(1000, update)  # call update every second


window = tk.Tk()
window.title('Planner')
window.resizable(0, 0)

style = ttk.Style()
style.theme_use('default')

font = ('Arial Bold', 10)
fg = 'darkblue'

# layout for school
school = tk.Frame(window, padx=10, pady=5)
school.grid(row=0, column=0, sticky='nsew')

cur_lesson = tk.Label(school, width=10, font=font, fg=fg, anchor='w')
progressbar = ttk.Progressbar(school, length=100)
next_lesson = tk.Label(school, width=16, font=font, fg=fg, anchor='w')

cur_lesson.grid(row=0, column=0, sticky='ew')
progressbar.grid(row=0, column=1, sticky='ew')
next_lesson.grid(row=1, column=1, sticky='ew')

# layout for no school
no_school = tk.Label(window, text='Relax - No School!', font=font, fg=fg, padx=10, pady=10)
no_school.grid(row=0, column=0, sticky='nsew')

# start update
update()

window.mainloop()
acw1668
  • 40,144
  • 5
  • 22
  • 34