Search code examples
pythonuser-interfacetkintergeopy

Need to create option for km or mi using Tkinter and Python


So below I have a code that I found and modified for calculating the distance between two locations. I am creating a GUI for simple user input. Everything is working as expected but it would be a bonus if I could accomplish two things.

  1. Have a toggle or selection that would allow me to show the distance in either KM or Mi

  2. is there any way that I could round the output so it doesn't have so many digits after the decimal?

I assume it has to be some type of a variable based on the object selection?

# import modules 
from tkinter import *
from geopy.geocoders import Nominatim 
from geopy import distance 

# user defined funtion 
def get_dis(): 
  try: 
      
      geolocator = Nominatim(user_agent="geoapiExercises") 
      
      place1 = geolocator.geocode(str(e1.get())) 
      place2 = geolocator.geocode(str(e2.get())) 


      Loc1_lat,Loc1_lon = (place1.latitude),(place1.longitude) 
      Loc2_lat,Loc2_lon = (place2.latitude),(place2.longitude) 

      location1=(Loc1_lat,Loc1_lon) 
      location2=(Loc2_lat,Loc2_lon) 

      res = (str(distance.distance(location1, location2).mi)+" Mi") 

      result.set(res) 
  except: 
      result.set("someting went wrong") 

# object of tkinter 
# with background set to light grey 
master = Tk() 
master.configure(bg='light grey') 
master.title("Find Distance") 

# Variable Classes in tkinter 
result = StringVar(); 


# Creating label for each information 
# name using widget Label 
Label(master, text="Start Location : " , bg = "light grey").grid(row=1, sticky=W) 
Label(master, text="End Location : " , bg = "light grey").grid(row=2, sticky=W) 

Label(master, text="Result :", bg = "light grey").grid(row=3, sticky=W) 

# Creating label for class variable 
# name using widget Entry 
Label(master, text="", textvariable=result,bg = "light grey").grid(row=3,column=1, sticky=W) 


e1 = Entry(master,width = 50) 
e1.grid(row=1, column=1) 
e2 = Entry(master,width = 50) 
e2.grid(row=2, column=1) 

# creating a button using the widget 
b = Button(master, text="Check", command=get_dis, bg = "white") 
b.grid(row=1, column=2,columnspan=2, rowspan=2,padx=5, pady=5,) 

mainloop()

edit with notes.. cant get to round

import modules from tkinter import * from geopy.geocoders import Nominatim from geopy import distance

user defined funtion def get_dis():

try: 
      
    geolocator = Nominatim(user_agent="geoapiExercises") 
      
    place1 = geolocator.geocode(str(e1.get())) 
    place2 = geolocator.geocode(str(e2.get())) 


    Loc1_lat,Loc1_lon = (place1.latitude),(place1.longitude) 
    Loc2_lat,Loc2_lon = (place2.latitude),(place2.longitude) 

    location1=(Loc1_lat,Loc1_lon) 
    location2=(Loc2_lat,Loc2_lon) 

    res = (str(distance.distance(location1, location2) .km)+" Km") 

    result.set(res) 
except: 
    result.set("someting went wrong") 

def get_dis():

    if unit.get() == 'mi':
        res = str(round(distance.distance(location1, location2).mi, 2))+" Mi"
    else:
        res = str(round(distance.distance(location1, location2).km, 2))+" km"   

object of tkinter

with background set to light grey master = Tk() master.configure(bg='light grey') master.title("Find Distance")

Variable Classes in tkinter result = StringVar(); Label(master, text="", textvariable=result,bg = "light grey").grid(row=4,column=1,

sticky=W)

Creating label for each information

name using widget Label Label(master, text="Start Location : " , bg = "light grey").grid(row=1, sticky=W) Label(master, text="End

Location : " , bg = "light grey").grid(row=2, sticky=W)
Label(master, text="Distance :", bg = "light grey").grid(row=3, sticky=W)

Creating label for class variable

name using widget Entry Label(master, text="Unit :", bg="light gray").grid(row=3, sticky=W) Label(master, text="Result :", bg =

"light grey").grid(row=4, sticky=W) e1 = Entry(master,width = 50) e1.grid(row=1, column=1) e2 = Entry(master,width = 50) e2.grid(row=2, column=1)

f1 = Frame(master) f1.grid(row=3, column=1, sticky=W) unit = StringVar(value="mi") Radiobutton(f1, text="miles", value="mi", variable=unit, bg="light gray").pack(side="left") Radiobutton(f1, text="km", value="km", variable=unit, bg="light gray").pack(side="left")

creating a button using the widget b = Button(master, text="Calculate", command=get_dis, bg = "white") b.grid(row=1,

column=2,columnspan=2, rowspan=2,padx=5, pady=5,) mainloop()


Solution

  • First add two radiobuttons before result row:

    Label(master, text="Unit :", bg="light gray").grid(row=3, sticky=W)
    Label(master, text="Result :", bg = "light grey").grid(row=4, sticky=W) # changed to row 4
    ...
    f1 = Frame(master)
    f1.grid(row=3, column=1, sticky=W)
    unit = StringVar(value="mi")
    Radiobutton(f1, text="miles", value="mi", variable=unit, bg="light gray").pack(side="left")
    Radiobutton(f1, text="km", value="km", variable=unit, bg="light gray").pack(side="left")
    
    result = StringVar(); 
    Label(master, text="", textvariable=result,bg = "light grey").grid(row=4,column=1, sticky=W) # changed to row 4
    

    Then call the corresponding function based on the unit selected inside get_dis():

    def get_dis():
        try:
            ...
            if unit.get() == 'mi':
                res = str(round(distance.distance(location1, location2).mi, 3))+" Mi"
            else:
                res = str(round(distance.distance(location1, location2).km, 3))+" km"
        ...
    

    Note that round(..., 3) is used to round the result to have 3 digits after the decimal.