Zac T
Zac T

Reputation: 1

How to make tkinter update value continuously

I am trying to write a program that calculates one's grade for a class. The way I have it structured is that the user can add exams, projects, labs, or whatever and each has a certain weight. For now I am just trying to get it to work only with exams. The problem is that my final grade is stuck at 0, because it records the grade as the default value, zero. How can I make it record the new value OR even better is there a way to just take the values of a certain column in tkinter?

def ShowFinalGrade(self):


    Label(self, text= "Final Grade").grid(row=10, column=0, columnspan=3)
    Label(self, text= self.Calculate()).grid(row=10, column=4)
    finalpercent=87
    fp = finalpercent
    grading_scale = self.CreateGradeScale()

    self.class_score = Button(self, text="Calculate Grade", command=self.Calculate)
    self.class_score.grid(row=10, column=5, padx=50)



    if fp>= grading_scale[0]:
        self.finalgrade= "A"
    elif fp>= grading_scale[1]:
        self.finalgrade= "A-"
    elif fp>= grading_scale[2]:
        self.finalgrade= "B+"
    elif fp>= grading_scale[3]:
        self.finalgrade= "B"
    elif fp>= grading_scale[4]:
        self.finalgrade= "B-"
    elif fp>= grading_scale[5]:
        self.finalgrade= "C+"
    elif fp>= grading_scale[6]:
        self.finalgrade= "C"
    elif fp>= grading_scale[7]:
        self.finalgrade= "C-"
    elif fp>= grading_scale[8]:
        self.finalgrade= "D+"
    elif fp>= grading_scale[9]:
        self.finalgrade= "D"
    else:
        self.finalgrade= "F"

    Label(self, text = self.finalgrade).grid(row=10, column=3, columnspan=3)



def AddExam(self):
    examnumber = self.examnumber
    examname = Entry(self)
    examname.grid(row=examnumber+1, column=0)
    examname.insert(0, "Exam "+str(examnumber))
    examgrade = Entry(self)
    examgrade.grid(row=examnumber+1, column=1)
    examgrade.insert(0,0)
    # self.examtotal += float(examgrade.get())
    self.examscores.append(float(examgrade.get()))
    print(examgrade) # Troubleshooting
    self.examnumber+=1


def Calculate(self):
    examsum = 0
    if len(self.examscores)!=0:
        for i in range(len(self.examscores)):
            examsum+= self.examscores[i]
        examavg = examsum / len(self.examscores)
    else:
        examavg = 0
    return examavg

Upvotes: 0

Views: 482

Answers (1)

Mario Camilleri
Mario Camilleri

Reputation: 1557

When you set the label to text=self.Calculate(), Python merely executes the function Calculate at that point and uses its returned result as the label text.

If you want tkinter to automatically update the label every time a new calculation is performed, then the cleanest way to do it is to use a StringVar:

self.examAverage = tk.StringVar()
Label(self, textvariable=self.examAverage).grid(row=10, column=4)

and then in Calculate, instead of

return examavg

do

self.eaxmAverage.set(examavg)

May I also propose a more Pythonic way of mapping the mark fp to a grade - your approach, though valid, does not use the Python idiom. For example, you may try:

def getGrade(self, fp):

    #example grading scale
    gradeBoundaries = [(95, 'A'), (85, 'A-'), (75, 'B+'),
                       (65, 'B'), (60, 'B-'), (55, 'C+'),
                       (50, 'C'), (45, 'C-'), (40, 'D+'),
                       (35, 'D'), (0, 'F')]

    return next((grade for mark,grade in gradeBoundaries if fp>=mark),'Error')

Or, if you wish to keep the grading scale separate from the grades (since it may change from exam to exam), you may try:

def getGrade(self, fp, grading_scale):
    grades = 'A A- B+ B B- C+ C C- D+ D F'.split(' ')

    return next((grade for mark, grade in zip(grading_scale, grades) if fp >= mark), 'Error')

and then supply the grading scale either as an instance variable, or as an argument:

getGrade(70,[95,85,75,65,60,55,50,45,40,35,0])

Upvotes: 1

Related Questions