diff --git a/main.py b/main.py index 0f6d05e..fc65518 100644 --- a/main.py +++ b/main.py @@ -1,105 +1,127 @@ -from tkinter import * -from tkinter.ttk import * +import tkinter as tk # using tkinter for the GUI +import tkinter.ttk as ttk -class Window(Frame): +class Window(tk.Frame): # create a tkinter frame def __init__(self, master=None): - Frame.__init__(self, master) + tk.Frame.__init__(self, master) self.master = master -root = Tk() +root = tk.Tk() # some definitions for the GUi app = Window(root) -def add_base(): +##### Functions ##### + +def addBase(): # the addBase function will add whatever base is in the baseInput entry box with the button is pressed out = [] - for x in baseList['values']: - out.append(int(x)) + for base in baseList['values']: # create a list that is a copy of the base list, but as integers instead of strings (so it can be sorted) + out.append(int(base)) try: - if not int(baseInput.get()) in out: - out.append(int(baseInput.get())) - baseList['values'] = sorted(out) - functionTrigger(0,0,0) # Trigger number conversion if a base is added - except ValueError: - listOut.delete(0,listOut.size()) - listOut.insert(END, "Not a valid base!") - -def functionTrigger(a,b,c): # Positional arguments from the trace are not needed for this program, but still must be defined - input = numberInput.get() + if not int(baseInput.get()) in out: # if the base isn't already there, + out.append(int(baseInput.get())) # then add it to the list + baseList['values'] = sorted(out) # apply the list to the dropdown, after sorting it + functionTrigger(0,0,0) # Trigger number conversion + except ValueError: # error is raised if the base is not a number + displayMessage("Not a valid base!") + +# functionTrigger is ran when the number input box is changed, or when a base is added +def functionTrigger(a,b,c): # Positional arguments are not used for this function to run, but still must be defined to allow the finction to be called by a tracer + input = numberInput.get() # Retreive the input number base = int(baseList['values'][baseList.current()]) # Retreive the current selected base - baseConverter(input, base) + baseConverter(input, base) # run the conversion with the selected base and input + +# displayMessage will simply write a message to the output listbox. +def displayMessage(message): + listOut.delete(0,listOut.size()) # delete all existing entries + listOut.insert(tk.END, message) # add a line with the message + -def baseConverter(userInput, numberBase): +def baseConverter(userInput, numberBase): # arguments: userInput: the user's number to be converted. numberBase: the number base of the input try: - decimalNum = int(userInput,numberBase) # First attempt to get the number in decimal. - except: - listOut.delete(0,listOut.size()) - listOut.insert(END, "Number entered does not match the base!") + decimalNum = int(userInput,numberBase) # First, try to get the number in decimal. + except: # If this fails, then the input from the user does not work in this base, or might not be a number at all + displayMessage("Number entered does not match the base!") return - listOut.delete(0,listOut.size()) + listOut.delete(0,listOut.size()) # clear the output for base in baseList['values']: # Iterate through all bases - outputText = "Base " + base + ": " + outputText = "Base " + base + ": " # prepare a string for the line outputNumber = "" - tempNum = decimalNum - while tempNum > 0: - digit = int(tempNum % int(base)) - tempNum = int(tempNum / int(base)) + tempNum = decimalNum # create a temp number to modify + + while tempNum > 0: # this loop converts from decimal to any other base + digit = int(tempNum % int(base)) # find a digit by taking remainder with the base + tempNum = int(tempNum / int(base)) # take the result of the division and use it for the next digit if digit < 10: # Can be represented with 0-9 - outputNumber += str(digit) + outputNumber += str(digit) # add the digit else: # Alphanumeric characters needed outputNumber += chr(55 + digit) # ASCII character offset for capital letters - outputNumber = outputNumber[::-1] - outputText += outputNumber - listOut.insert(END, outputText) + + outputNumber = outputNumber[::-1] # reverse the output number, as the above loop added digits in reverse + outputText += outputNumber + listOut.insert(tk.END, outputText) # insert the line into the output listbox at the end +##### Variables ##### -root.wm_title("Numerical converter") +root.wm_title("Numerical converter") # window title -lbl0 = Label(root, text="Add a base:", font=("Arial", 12)) +# Some labels. The empty ones make the spacing in the GUI better +lbl0 = tk.Label(root, text="Add a base:", font=("Arial", 12)) lbl0.grid(column=0, row=1) -lbl1 = Label(root, text="\n", font=("Arial", 12)) +lbl1 = tk.Label(root, text="\n", font=("Arial", 12)) lbl1.grid(column=1, row=0) -addBaseBtn = Button(root, text="Add", command=add_base) -addBaseBtn.grid(column=2, row=1) +lbl2 = tk.Label(root, text="", font=("Arial", 12)) +lbl2.grid(column=0, row=3) -baseInput = Entry(root,width=10, state='enabled') +# the add base button +addBaseBtn = tk.Button(root, text="Add", command=addBase) +addBaseBtn.grid(column=2, row=1) +# the entry box for the adding a base +baseInput = ttk.Entry(root,width=10, state='enabled') baseInput.grid(column = 1, row = 1) -lbl2 = Label(root, text="", font=("Arial", 12)) -lbl2.grid(column=0, row=3) -separator1 = Separator(root, orient='horizontal') +# some horizontal separators for the app +separator1 = ttk.Separator(root, orient='horizontal') separator1.place(relx=0, rely=0.2, relwidth=1, relheight=1) -separator2 = Separator(root, orient='horizontal') +separator2 = ttk.Separator(root, orient='horizontal') separator2.place(relx=0, rely=0.43, relwidth=1, relheight=1) -baseList = Combobox(root, width='10') +# the dropdown list of bases +baseList = ttk.Combobox(root, width='10') baseList['values']= (2, 10, 16) -baseList.current(1) #set the selected item +baseList.current(1) #set the default item to base 10 baseList.grid(column=1, row=4) -lbl3 = Label(root, text="\nNumber Base \n of the input:\n", font=("Arial", 12)) + +# label for the base dropdown +lbl3 = tk.Label(root, text="\nNumber Base \n of the input:\n", font=("Arial", 12)) lbl3.grid(column=0, row=4) -userInputRaw = StringVar() -userInputRaw.trace_add("write", functionTrigger) +# create a tracable string for the text input; when this text is changed, the base conversion is ran +userInputRaw = tk.StringVar() +userInputRaw.trace_add("write", functionTrigger) # trace the changes made to the string, when it changes run functionTrigger -numberInput = Entry(root,width=10, state='enabled', textvariable=userInputRaw) +# number input for the user, that uses the above traced variable +numberInput = ttk.Entry(root,width=10, state='enabled', textvariable=userInputRaw) numberInput.grid(column=1, row = 6) -lbl4 = Label(root, text="Number to convert:", font=("Arial", 12)) +# Label for number input +lbl4 = tk.Label(root, text="Number to convert:", font=("Arial", 12)) lbl4.grid(column=0, row=6) -lbl5 = Label(root, text="", font=("Arial", 12)) +# Label to improve spacing +lbl5 = tk.Label(root, text="", font=("Arial", 12)) lbl5.grid(column=50, row=5) - -listOut = Listbox(root, selectmode='SINGLE', width=50) +# Output listbox +listOut = tk.Listbox(root, selectmode='SINGLE', width=50) listOut.grid(column=0, row=7, columnspan=3) - +# disable app resizing root.resizable(False, False) root.geometry('325x400') +# run the app root.mainloop()