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 = " \n Number 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 ( )