You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
5.6 KiB
Python
132 lines
5.6 KiB
Python
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()
|