简体   繁体   中英

GPA Calculator Program in Python with a tkinter GUI

I'm trying to create a GPA calculator in python using tkinter. I'm using python 3.1. Heres what I have so far for my GUI.

    root = Tk()
    root.title('GPA Calculator')

    #create frames
    self.column_headers = Frame(root)
    self.class1_frame = Frame(root)
    self.class2_frame = Frame(root)
    self.class3_frame = Frame(root)
    self.class4_frame = Frame(root)
    self.enterClasses_frame= Frame(root)
    self.deposit_frame = Frame(root)


    self.column_header = Label(self.column_headers, \
    text = 'Credit Hours                        Grade',fg = 'black')
    self.column_header.pack(side = 'left')

    self.class1label = Label(self.class1_frame, \
        text = 'Class 1:', fg = 'black')
    self.class1label.pack(side = 'left')
    self.creditHours1 = Entry(self.class1_frame)
    self.creditHours1.pack(side = 'left')
    self.grade1 = Entry(self.class1_frame)
    self.grade1.pack(side = 'left')

    self.class2label = Label(self.class2_frame, \
        text = 'Class 2:', fg = 'black')
    self.class2label.pack(side = 'left')
    self.creditHours2 = Entry(self.class2_frame)
    self.creditHours2.pack(side = 'left')
    self.grade2 = Entry(self.class2_frame)
    self.grade2.pack(side = 'left')


    self.class3label = Label(self.class3_frame, \
    text = 'Class 3:', fg = 'black')
    self.class3label.pack(side = 'left')
    self.creditHours3 = Entry(self.class3_frame)
    self.creditHours3.pack(side = 'left')
    self.grade3 = Entry(self.class3_frame)
    self.grade3.pack(side = 'left')


    self.class4label = Label(self.class4_frame, \
    text = 'Class 4:', fg = 'black')
    self.class4label.pack(side = 'left')
    self.creditHours4 = Entry(self.class4_frame)
    self.creditHours4.pack(side = 'left')
    self.grade4 = Entry(self.class4_frame)
    self.grade4.pack(side = 'left')


    self.enterClasses = Button(self.enterClasses_frame, text = 'Submit Classes',bg = 'blue',\
        fg = 'white')
    self.enterClasses.pack(side = 'left')



    #pack frames
    self.column_headers.pack()
    self.class1_frame.pack()
    self.class2_frame.pack()
    self.class3_frame.pack()
    self.class4_frame.pack()
    self.enterClasses_frame.pack()


    root.mainloop()

I want to make it so for the Grades I have a dropdown box or something similar that can give them the option to select their grades like A,A-,B+,B etc etc..

I've done a lot of research and although I've touched upon it a little bit I have no idea how to incorporate it into my GUI.

Any help would be greatly appreciated, thanks in advance.

So, I completely agree with jon_darkstar about not hardcoding the courses. This looks like a prime candidate for it's own class (in the programming concept sense).

But, to replace your Entry boxes with dropdowns (known as * OptionMenu *s), you'd do the following:

self.class1label = Label(self.class1_frame, \
    text = 'Class 1:', fg = 'black')
self.class1label.pack(side = 'left')
self.creditHours1 = Entry(self.class1_frame)
self.creditHours1.pack(side = 'left')
#self.grade1 = Entry(self.class1_frame)
#self.grade1.pack(side = 'left')
self.grade1 = StringVar(root)
self.grade1.set("  ")
self.g1opt = OptionMenu(self.class1_frame, self.grade1, *GRADES)
self.g1opt.pack(side = 'right')

Note that I commented out your Entry lines and added my own below.

Also, I defined GRADES before I referenced it as:

GRADES = ["A","B","C","D","F"]

but you could modify that to meet your needs (with +/- grades, etc).

You should also consider creating a callback function that is called anytime a user changes the value of the dropdown (or opens the dropdown and re-selects the current selection). You would do that by first creating a callback function, eg

def dd_cb(selected):
    print("Dropdown Callback: ", selected)

Then editing the second to last line in the above section to something like the following for each course:

self.g1opt = OptionMenu(self.class1_frame, self.grade1, *GRADES, command=dd_cb)

I should point out that you won't be able to detect which dropdown was changed doing it this way, so this is yet another reason to makes these individual rows instances of a class. If you did that, you would write something like:

self.g1opt = OptionMenu(self.class1_frame, self.grade1, *GRADES, command=self.dd_cb)

instead.

I got carried away...

And got you started moving towards each course being an instance of a class.

gpacalc.py

from tkinter import *
import Course

class App(object):

    def __init__(self):
        root = Tk()
        root.title('GPA Calculator')

        self.column_headers = Frame(root)
        self.enterClasses_frame= Frame(root)
        self.deposit_frame = Frame(root)

        self.column_header = Label(self.column_headers, \
        text = 'Credit Hours                                   Grade',fg = 'black')
        self.column_header.pack(side = 'left')

        self.enterClasses = Button(self.enterClasses_frame, text='Submit Classes', bg='blue',\
            fg='white')
        self.enterClasses.pack(side = 'left')

        # Define the number of Courses -- eventually, you might want to make this user-editable
        NUM_COURSES = 4

        # Create Courses
        self.courses = list()
        for i in range(1, NUM_COURSES+1):
            self.courses.append(Course.Course(root, i))


        # Pack Frames
        self.column_headers.pack()
        for c in self.courses:
            c.pack()
        self.enterClasses_frame.pack()


        root.mainloop()

a = App()

Course.py

import tkinter

GRADES = ["A","B","C","D","F"]

class Course(object):


    def __init__(self, root, course_id):
        # Store Course ID
        self.course_id = course_id
        # Create Frame
        self.frame = tkinter.Frame(root)
        # Create Label
        self.label = tkinter.Label(self.frame, text = ('Class %d:' % course_id), fg = 'black')
        self.label.pack(side = 'left')
        # Create Credit Hours Entry
        self.hours = tkinter.Entry(self.frame)
        self.hours.pack(side = 'left')
        # Create Grade Dropdown
        self.grade = tkinter.StringVar(root)
        self.grade.set("  ")
        self.gopt = tkinter.OptionMenu(self.frame, self.grade, *GRADES, command=self.dd_cb)
        self.gopt.pack(side = 'left')

    def dd_cb(self, selected):
        print("Course %d Dropdown Event: %s" % (self.course_id, selected))

    def pack(self):
        self.frame.pack()

A couple things to note here:

1) Now, the callback will be able to tell which dropdown was changed. Try it, you should get output like:

Course 1 Dropdown Event: A
Course 2 Dropdown Event: B
Course 3 Dropdown Event: C

2) You can change the number of courses by editing the NUM_COURSES variable.

3) This is not perfect, and I do a lot more tweaking -- but this get you off in the right direction if you intend on cleaning up your code by making each course and instance of a class.

(Upvotes for a new editor appreciated)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM