From 676d30d65c921bb8784db371b98ae82efce25350 Mon Sep 17 00:00:00 2001 From: mputzlocher Date: Tue, 4 Jan 2022 15:50:23 +0000 Subject: [PATCH] grades4 example --- tk_first_steps/grades4.py | 386 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 tk_first_steps/grades4.py diff --git a/tk_first_steps/grades4.py b/tk_first_steps/grades4.py new file mode 100644 index 0000000..2465953 --- /dev/null +++ b/tk_first_steps/grades4.py @@ -0,0 +1,386 @@ +#!/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() \ No newline at end of file