-1

I am trying to use GPS sensor with RPI and make its GUI using Tkinter. I want to update my GPS value and shows in the GUI. But in GUI it shows only initial value. In backend GPS value is updating but unable to show in GUI.

import tkinter as tk
import serial
import time
import webbrowser as wb


ser = serial.Serial('/dev/ttyUSB0', 9600)

class IotCar(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        width=tk.Tk.winfo_screenwidth(self)
        height=tk.Tk.winfo_screenheight(self)
        tk.Tk.geometry(self, '{}x{}'.format(width, height))


        container=tk.Frame(self)
        container.pack(side='top', fill='both', expand='True')
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for each_frame in (StartPage, HomePage):
            frame = each_frame(container, self)
            self.frames[each_frame]=frame
            frame.grid(row=0, column=0, sticky='nsew')
        self.show_page(StartPage)

    def show_page(self, cont):

        frame=self.frames[cont]
        frame.tkraise()

class StartPage(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        next_button = tk.Button(self, text='Next', command=lambda:
                                controller.show_page(HomePage)).pack(side=tk.TOP,padx=5, pady=5)
class HomePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.gps_pos()
        self.lat1 = tk.StringVar()
        self.lon1=tk.StringVar(self)
        self.label_lat = tk.Label(self.HomePage, text='Latitude', justify=tk.LEFT, padx=10).pack()
        self.label_lat1 = tk.Label(self.HomePage, textvariable=self.lat1, justify=tk.LEFT,
                              borderwidth=2, relief='ridge').pack()
        self.label_lon = tk.Label(self, text='Longitude', justify=tk.LEFT, padx=10).pack()
        self.label_lon1 = tk.Label(self, text=self.lon1, justify=tk.LEFT,
                             borderwidth=2, relief='ridge').pack()

    def gps_pos(self):
        print('Entered into gps')
        ser.flushInput()
        ser.flushOutput()
        ser.write(b'AT+CGPSPWR=1\r')
        ser.write(b'AT+CGPSOUT=32\r')
        while True:
            gps=str(ser.readline())
            gps=gps[2:].split(',')
            if gps[0]=='$GPRMC' and gps[3]!='':
                lat=gps[1]
                lon=gps[1]
                break;
        self.after(3000,self.gps_pos)
        print(lat, lon)
        self.lat1.set(lat1)
app = IotCar()
app.mainloop()

Please help me to understand what is wrong in it. Thank you in advance.

1 Answers1

0

I am unable to run this script as I don't have the serial module however I have modified a few things and this populates the label with text (comments in code). You need a function that will assign the "text" parameters in the labels with a value.

import tkinter as tk
import time
import webbrowser as wb


class IotCar(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        width=tk.Tk.winfo_screenwidth(self)
        height=tk.Tk.winfo_screenheight(self)
        tk.Tk.geometry(self, '{}x{}'.format(width, height))


        container=tk.Frame(self)
        container.pack(side='top', fill='both', expand='True')
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for each_frame in (StartPage, HomePage):
            frame = each_frame(container, self)
            self.frames[each_frame]=frame
            frame.grid(row=0, column=0, sticky='nsew')
        self.show_page(StartPage)

    def show_page(self, cont):

        frame=self.frames[cont]
        frame.tkraise()

class StartPage(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        next_button = tk.Button(self, text='Next', command=lambda:
                                controller.show_page(HomePage)).pack(side=tk.TOP,padx=5, pady=5)
class HomePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        self.lat1 = tk.StringVar()
        self.lon1 = tk.StringVar(self)
        self.label_lat = tk.Label(self, text='Latitude', justify=tk.LEFT, padx=10)
        self.label_lat.pack()

        self.label_lat1 = tk.Label(self, justify=tk.LEFT,
                              borderwidth=2, relief='ridge') # I have removed the "text" parameter because my function will update it.
        self.label_lat1.pack()

        self.label_lon = tk.Label(self, text='Longitude', justify=tk.LEFT, padx=10)
        self.label_lon.pack()
        self.label_lon1 = tk.Label(self, justify=tk.LEFT,
                             borderwidth=2, relief='ridge') # I have removed the "text" parameter because my function will update it.
        self.label_lon1.pack()
        button = tk.Button(self, text="update label", bg= "#aaaaaa", fg ="#483F44",
         font=("Arial", 10, "bold"), relief="groove", command = lambda: helloworld()) # This button will run the helloworld function
        button.pack()

        def helloworld():
            self.label_lat1["text"] = "Hello" #This will update the text parameter in label_lat1 with "Hello"
            self.label_lon1["text"] = "World" #This will update the text parameter in label_lon1 with "World"

app = IotCar()
app.mainloop()

A few things to note is to pack/place/grid your labels separately from when you define its parameters i believe that the way you have currently set up the widget is giving it a None type which is why you can't assign text to it:

#You write
self.label_lat1 = tk.Label(self.HomePage, textvariable=self.lat1, justify=tk.LEFT,
                              borderwidth=2, relief='ridge').pack()

#My example
self.label_lat1 = tk.Label(self, justify=tk.LEFT,
                              borderwidth=2, relief='ridge')
self.label_lat1.pack()

You then need a command that will run a function and in that function will have a variable which will assign a text value to the label (i.e. the helloworld function in my code).

Looking at your code i believe you will need to amend the way you are packing your widgets and then in your function do something like

def gps_pos(self):

    print(lat, lon)
    self.label_lat1["text"] = lat 
    self.label_lon1["text"] = lon

Below is a very useful answer on how to layout your tkinter gui and various other FAQ. I myself found it extremely useful Switch between two frames in tkinter

RamWill
  • 288
  • 1
  • 3
  • 6