import tkinter as tk # using tkinter for the GUI import tkinter.ttk as ttk # Requirements to run: python3 pytk class Window(tk.Frame): # create a tkinter frame def __init__(self, master=None): tk.Frame.__init__(self, master) self.master = master root = tk.Tk() # some definitions for the gui app = Window(root) ##### Functions ##### def addBase(): # the addBase function will add whatever base is in the baseInput entry box with the button is pressed out = [] for base in baseDropdown['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: # if the base isn't already there, out.append(int(baseInput.get())) # then add it to the list baseDropdown['values'] = sorted(out) # apply the list to the dropdown, after sorting it functionTrigger(0,0,0) # Trigger number conversion except ValueError: # error is caught 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(baseDropdown['values'][baseDropdown.current()]) # Retreive the current selected base listOut.delete(0,listOut.size()) # clear the output output = baseConverter(input, base) # run the conversion with the selected base and input for line in output: # insert each line into the output listbox at the end listOut.insert(tk.END, line) # 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): # arguments: userInput: the user's number to be converted. numberBase: the number base of the input try: 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 outputList = [] for base in baseDropdown['values']: # iterate through all bases outputText = "Base " + base + ": " # prepare a string for the line outputNumber = "" 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) # add the digit else: # Alphanumeric characters needed outputNumber += chr(55 + digit) # ASCII character offset for capital letters outputNumber = outputNumber[::-1] # reverse the output number, as the above loop added digits in reverse outputText += outputNumber #add the number to the rest of the string outputList.append(outputText) # add each conversion to the output list return outputList # return the list of conversions ##### Variables ##### root.wm_title("Numerical converter") # window title # 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 = tk.Label(root, text="\n", font=("Arial", 12)) lbl1.grid(column=1, row=0) lbl2 = tk.Label(root, text="", font=("Arial", 12)) lbl2.grid(column=0, row=3) # 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) # some horizontal separators for the app separator1 = ttk.Separator(root, orient='horizontal') separator1.place(relx=0, rely=0.2, relwidth=1, relheight=1) separator2 = ttk.Separator(root, orient='horizontal') separator2.place(relx=0, rely=0.43, relwidth=1, relheight=1) # the dropdown list of bases baseDropdown = ttk.Combobox(root, width='10') baseDropdown['values']= (2, 10, 16) baseDropdown.current(1) #set the default item to base 10 baseDropdown.grid(column=1, row=4) # 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) # 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 # 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) # Label for number input lbl4 = tk.Label(root, text="Number to convert:", font=("Arial", 12)) lbl4.grid(column=0, row=6) # Label to improve spacing lbl5 = tk.Label(root, text="", font=("Arial", 12)) lbl5.grid(column=50, row=5) # 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()