(Feb-03-2024, 06:43 PM)deanhystad Wrote: [ -> ]You must be making two windows. tk.Tk() creates a window and tk.TopLevel() creates a window. Are you calling both in your program? If you only call tk.Tk() you will only have 1 window.
Posting a 200 line program is fine.
im not using top level. i know that creates a second window but like i said, i want only one window. my code follows
from tkinter import *
from tkinter import messagebox
import json
from datetime import datetime,timedelta
from tkcalendar import DateEntry
import calendar as cal
class WorkoutTracker:
def __init__(self, window,canvas):
self.window = window
self.day_value_inside= StringVar(self.window, value="Choose a date")
self.act_value_inside = StringVar(self.window, value="Choose a workout")
self.canvas=canvas
self.cur_row = 0
self.count = 0
self.updated_list,self.day_lbl,self.act_lbl, \
self.day_opt,self.act_opt,self.unit_lbl, \
self.unit_ent,self.min_lbl=[], [],[],[],[],[],[],[]
self.dates_list = self.all_dates_current_month()
self.pic_file = PhotoImage(file="./workout.png")
self.setup_gui()
self.add_column()
def all_dates_current_month(self,days=60,format="%a %d %B %Y"):
'''generates a list of all days inside the current month and returns it.
The dates are presented in a spcific format ("day name","date","month" and "year")'''
dates=[]
start=datetime.now() + timedelta(days=-30)
for x in range(-30,days+1):
dates.append((start + timedelta(days=x)).strftime(format))
print(dates)
return dates
def setup_gui(self):
# make a list of the 4 past and 4 upcoming days
for index, dat in enumerate(self.dates_list):
if dat == datetime.today().strftime('%a %d %B %Y'):
self.updated_list.extend(self.dates_list[index - 5:index+6])
self.window = Tk()
self.canvas.grid(row=0, column=1, columnspan=8)
pic = self.canvas.create_image(240, 135, image=self.pic_file)
remove_button=Button(text="Remove Last Entry",command=self.remove_button)
remove_button.grid(row=1,column=7)
gen_row_but = Button(text="Add entry", command=self.add_column)
gen_row_but.grid(row=1, column=8)
reg_but = Button(text="Register activities", command=self.reg_act)
reg_but.grid(row=1, column=9)
display_but = Button(text="Display Saved Activities", command=self.display_act)
display_but.grid(row=1, column=10)
def reg_act(self):
'''saves dates of workout, activities and duration in a dictionary setting and later saves these in a json file'''
try:
with open("saved_data.json", "r") as file:
saved_data = json.load(file)
except FileNotFoundError:
saved_data = {}
with open("saved_data.json", "w") as file:
json.dump(saved_data, file)
except json.decoder.JSONDecodeError:
saved_data = {}
finally:
for i in range(0, self.count):
day = self.day_value_inside.get()
activity = self.day_value_inside.title()
try:
unit = float(self.unit_ent[i].get())
except ValueError:
messagebox.showerror(title="Oooops", message="You have not entered duration information")
else:
if messagebox.askokcancel(title=f"{day} Workout Information",
message=f"Activity: {activity} for {unit} minutes.\nSave this activity?"):
if day in saved_data:
saved_data[day]["activity"].append(activity)
saved_data[day]["unit"].append(unit)
else:
new_data = {day: {"activity": [activity], "unit": [unit]}}
saved_data.update(new_data)
with open("saved_data.json", "w") as file:
json.dump(saved_data, file, indent=4)
def display_act(self):
'''makes a string of all activities within a specific date. uses messagebox to display each day as it is iterated through'''
try:
with open("saved_data.json", "r") as file:
data = json.load(file)
except json.decoder.JSONDecodeError:
data = {}
messagebox.showerror(title="Ooooops", message=f"There is no saved data to display")
finally:
data_str = ""
for key in data:
for i, act in enumerate(data[key]['activity']):
data_str += f"On {key} you did {data[key]['activity'][i].lower()} for {data[key]['unit'][i]} minutes.\n"
messagebox.showinfo(title=f"{key} Workout Information", message=f"{data_str}")
data_str = ""
def add_column(self):
'''generates a column of entries and labels
names of each entry and label are created dynamically
and each widget has a location added. Tkinter "rows" are incremented so each time this function is called
the next column of widgets gets generated below the previous'''
self.cur_row += 1
self.day_lbl.append(Label(text="On"))
self.day_lbl[-1].grid(row=self.cur_row, column=0)
self.day_opt.append(OptionMenu(self.window,self.day_value_inside, self.updated_list[0], self.updated_list[1],
self.updated_list[2], self.updated_list[3], self.updated_list[4],
self.updated_list[5], self.updated_list[6], self.updated_list[7],
self.updated_list[8], self.updated_list[9]))
self.day_opt[-1].grid(row=self.cur_row, column=1)
self.act_lbl.append(Label(text="i did"))
self.act_lbl[-1].grid(row=self.cur_row,column=2)
self.act_opt.append(OptionMenu(self.window,self.act_value_inside,"Aerobics", "Cycling","Running", "Swimming", "Walking"))
self.act_opt[-1].grid(row=self.cur_row,column=3)
self.unit_lbl.append(Label(text="for: "))
self.unit_lbl[-1].grid(row=self.cur_row,column=4)
self.unit_ent.append(Entry())
self.unit_ent[-1].grid(row=self.cur_row,column=5)
self.min_lbl.append(Label(text="minutes"))
self.min_lbl[-1].grid(row=self.cur_row,column=6)
self.count += 1
def remove_button(self):
self.day_lbl[-1].forget()
self.act_lbl[-1].forget()
self.day_opt[-1].forget()
self.act_opt[-1].forget()
self.unit_lbl[-1].forget()
self.unit_ent[-1].forget()
self.min_lbl[-1].forget()
self.count-=1
def display_act(self):
'''makes a string of all activities within a specific date. uses messagebox to display each day as it is iterated through'''
try:
with open("saved_data.json", "r") as file:
data = json.load(file)
except json.decoder.JSONDecodeError:
data = {}
messagebox.showerror(title="Ooooops", message=f"There is no saved data to display")
finally:
data_str = ""
for key in data:
for i, act in enumerate(data[key]['activity']):
data_str += f"On {key} you did {data[key]['activity'][i].lower()} for {data[key]['unit'][i]} minutes.\n"
messagebox.showinfo(title=f"{key} Workout Information", message=f"{data_str}")
data_str = ""
if __name__ == "__main__":
window = Tk()
window.title("Workout Tracker")
canvas=Canvas(width=400,height=227)
tracker = WorkoutTracker(window,canvas)
window.mainloop()