#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Tue Dec 10 19:58:52 2019 @author: mputzlocher """ import tkinter as tk from math import floor #+++++++++++++++++++++++ # Model #+++++++++++++++++++++++ grades = list() average = 0 def calc_average(): gsum = 0 cnt = 0 for g in grades: gsum += g cnt += 1 if cnt > 0: avg = gsum / cnt else: avg = 0 avgout = floor(avg * 100) / 100 return avgout #+++++++++++++++++++++++ # Controller #+++++++++++++++++++++++ class Controller(): def __init__(self, app): self.app = app self.vali = Validator(self) def update_avg(self): a = calc_average() app.update_avg(a) global average average = a def add_grade(self, event=None): try: g = self.app.grade.get() print(g) except: print("no value") return False grades.append(g) print(grades) self.app.update_entries(grades) self.app.update_canvas_histo() self.app.update_canvas_circ() self.app.update_cnt(len(grades)) self.update_avg() def del_last_entry(self, event=None): if len(grades) > 0: grades.pop() self.app.update_entries(grades) self.app.update_canvas_histo() self.app.update_canvas_circ() self.app.update_cnt(len(grades)) self.update_avg() else: # Nothing to do pass def save_to_file(self, event=None): f = open("mygrades.dat", "w+") for g in grades: f.write(str(g) + "\n") f.write("----------\n") f.write(str(average)) f.close() #+++++++++++++++++++++++ # Validator #+++++++++++++++++++++++ class Validator(): def __init__(self, controller): self.con = controller def validateGrade(self, P): print("got {}".format(P)) if P == "": return True else: pass try: P_num = int(P) if P_num <= 6 and P_num >= 1: return True else: print("not in range") return False except: print("no number") return False ## +++++++++++++++ # View ## +++++++++++++++ class MainWindow(tk.Frame): def __init__(self, master=None): super().__init__(master) self.master = master #top=self.winfo_toplevel() #top.rowconfigure(0, weight=1) #top.columnconfigure(0, weight=1) #self.rowconfigure(0, weight=1) #self.columnconfigure(0, weight=1) self.grid(sticky=tk.N+tk.S+tk.E+tk.W) #self.configure(width=500, height=500) self.create_widgets() self.controller = Controller(self) self.activate_controller() def create_widgets(self): self.rowconfigure(0, weight=1) self.f_input = tk.LabelFrame(self, text="Eingabe") self.f_input.grid(row=0, column=0, sticky="nwse") self.f_input.rowconfigure(0, weight=1) self.f_input.columnconfigure(0, weight=1) self.f_input.columnconfigure(1, weight=1) self.f_input.columnconfigure(2, weight=1) self.grade = tk.IntVar() self.grade.set(1) self.e_grade = tk.Entry(self.f_input, width = 3, textvariable=self.grade, bd=2, justify="center", bg="white", fg="blue") self.e_grade.grid(row = 0, column = 0, sticky="we") self.e_grade.focus() self.e_grade.select_range(0,"end") self.b_grade = tk.Button(self.f_input, text="Eintragen", padx=5, pady=2) self.b_grade.grid(row = 0, column = 1, sticky = "e") self.b_del_last = tk.Button(self.f_input, text="Letzte Löschen", padx=5, pady=2) self.b_del_last.grid(row = 0, column = 2, sticky = "e") self.b_load = tk.Button(self, text="Laden") self.b_load.grid(row = 0, column = 2) #self.ll_entries = tk.Label(self, text="Einträge:") #self.ll_entries.grid(row = 1, column = 0) self.f_entries = tk.LabelFrame(self, text="Einträge") self.f_entries.grid(row = 1, column = 0, sticky="nwse") self.l_entries = tk.Label(self.f_entries, text="") self.l_entries.grid(row = 0, column = 0, sticky = "we") self.f_data = tk.LabelFrame(self, text="Daten") self.f_data.grid(row = 2, column = 0, sticky="nwse") self.f_data.columnconfigure(0, weight=1) self.f_data.columnconfigure(1, weight=1) self.f_avg = tk.Frame(self.f_data) self.f_avg.grid(row=0, column=0) self.ll_avg = tk.Label(self.f_avg, text="Durchschnitt:") self.ll_avg.grid(row = 0, column = 0) self.l_avg = tk.Label(self.f_avg, text="") self.l_avg.grid(row = 0, column = 1) self.f_cnt = tk.Frame(self.f_data) self.f_cnt.grid(row=0, column=1) self.ll_cnt = tk.Label(self.f_cnt, text="Anzahl:") self.ll_cnt.grid(row = 0, column = 0) self.l_cnt = tk.Label(self.f_cnt, text="0") self.l_cnt.grid(row = 0, column = 1) self.b_save = tk.Button(self, text="Speichern") self.b_save.grid(row = 2, column = 2) self.f_diagrams = tk.Frame(self) self.f_diagrams.grid(row=3, column = 0, sticky="nwse") self.cv_histo = tk.Canvas(self.f_diagrams, width = 210, height = 140, bg="white") self.cv_histo.grid(row=3, column = 0) self.fill_canvas_histo() self.cv_circ = tk.Canvas(self.f_diagrams, width = 125, height = 125, bg = "lightgray") self.cv_circ.grid(row=3, column = 1) self.fill_canvas_circ() def fill_canvas_histo(self): cv = self.cv_histo cv.update_idletasks() maxw = cv.winfo_width() maxh = cv.winfo_height() diagh = maxh - 30 w = (maxw-20) // 6 - 4 border = 10 dist = 4 #columns = list() #columns_counts = list() for i in range(6): left = border + dist + i*(w + dist) tag = "c"+str(i+1) c = cv.create_rectangle(left, diagh, left +w, diagh, fill="blue", tags=(tag)) #columns.append(c) if i>0 and i % 2 == 0: cv.create_line(left - 2, maxh, left - 2, diagh, fill="gray", dash="2 1") else: pass pos = left + w //2 tag = "cnt"+str(i+1) cl = cv.create_text(pos, diagh-8, text="0", tags=(tag), fill="white", font="sans 8") #columns_counts.append(cl) tag = "pc"+str(i+1) cp = cv.create_text(pos, diagh+8, text="0 %", tags=(tag), fill="black", font="sans 8") if i % 2 == 0: pos = left + (2*w + dist)//2 tag = "pc2step"+str(i+1) cp2 = cv.create_text(pos, diagh+20, text="0 %", tags=(tag), fill="black", font="sans 8") else: pass def update_canvas_histo(self): cv = self.cv_histo maxh = cv.winfo_height() maxw = cv.winfo_width() diagh = maxh - 30 w = (maxw-20) // 6 - 4 border = 10 dist = 4 maxcount = 0 counts = list() percentages = list() l = len(grades) for i in range(6): grade = i+1 cnt = grades.count(grade) counts.append(cnt) if l > 0: p = int(round(cnt/l*100,0)) else: p = 0 percentages.append(p) if cnt > maxcount: maxcount = cnt else: pass if maxcount > 0: step = (diagh-10) // maxcount else: step = 0 for i in range(6): left = border + dist + i*(w + dist) tag = "c"+str(i+1) height = counts[i] * step cv.coords(tag, (left, diagh, left +w, diagh-height)) pos = left + w //2 tag = "cnt"+str(i+1) cv.coords(tag, (pos, diagh-height+6)) cv.itemconfigure(tag, text=str(counts[i])) tag = "pc"+str(i+1) cv.itemconfigure(tag, text=str(percentages[i]) + " %") if i % 2 == 0: pos = left + (2*w + dist)//2 tag = "pc2step"+str(i+1) if l > 0: p = int(round((counts[i] + counts[i+1])/l*100,0)) else: p = 0 cv.itemconfigure(tag, text = str(p) + " %") else: pass def fill_canvas_circ(self): cv = self.cv_circ cv.update_idletasks() maxw = cv.winfo_width() maxh = cv.winfo_height() center = [maxw // 2, maxh // 2] radius = maxh // 2 - 2 colors = ["#3bd63b", "#30adad", "#ff9a46", "#ff9797", "#ff4646", "#d00404"] parts = list() for i in range(6): tag = "p"+str(i+1) c = cv.create_arc(center[0]-radius, center[1]-radius, center[0]+radius, center[1]+radius, fill=colors[i], tags=(tag), activewidth=3, activeoutline = "white", start = 0, extent = 0) parts.append(c) def update_canvas_circ(self): cv = self.cv_circ cv.update_idletasks() cnt_all = len(grades) counts = list() for i in range(6): grade = i+1 cnt = grades.count(grade) counts.append(cnt) if cnt_all > 0: angles = [360*cnt / cnt_all for cnt in counts] else: angles = [0 for cnt in counts] startangles = [0] partsum = 0 for i in range(5): partsum += angles[i] startangles.append(partsum) for i in range(6): tag = "p"+str(i+1) startangle = startangles[i] extangle = angles[i] #print("from {} extent {}".format(startangle, extangle)) cv.itemconfig(tag, start=startangle, extent= extangle) cv.update_idletasks() def update_cnt(self, c): self.l_cnt["text"] = str(c) def update_avg(self, a): self.l_avg["text"] = str(a) def update_entries(self, grades): entries_str = grades self.l_entries["text"] = entries_str self.e_grade.focus() self.e_grade.select_range(0,"end") def activate_controller(self): vcmd = (self.e_grade.register(self.controller.vali.validateGrade), '%P') self.e_grade.bind("", self.controller.add_grade) self.e_grade.bind("", self.controller.add_grade) self.e_grade["validate"]="key" self.e_grade["validatecommand"]=vcmd self.b_grade["command"] = self.controller.add_grade self.b_del_last["command"] = self.controller.del_last_entry self.b_save["command"] = self.controller.save_to_file ## +++++++++++++++ # Ausführung ## +++++++++++++++ root = tk.Tk() root.title("Notendurchschnitt") #root.attributes('-zoomed', True) app = MainWindow(master=root) app.mainloop()