Tkinter unable to update label text - python

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.

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

Related

Trying to avoid combining .pack() and .grid() using tkinter and struggling. Which option is better and why?

I have been working on a developing a GUI using Python, Tkinter and Pillow (simple UI for a work application I am working on). I consistently run into an issue about the geometry manager running into issues because you 'cannot use geometry manager grid inside . which already has slaves managed by pack'.
This issues only happens when I add my class page_Roster to the application. I am not sure what I am doing run, but I suspect I must have goofed something up with the __init__ declaration or instantiation. Any help appreciated, but certainly chief among my concerns is figuring out how to work with which geometry manager in tkinter and when/why!
import tkinter as tk
from tkinter import font as tkfont
from tkinter import *
import importlib
from PIL import *
from PIL import Image
from PIL import ImageTk
class BellBankLMS(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=14, weight="bold", slant="italic")
self.title('Bell Bank: Learning Management Software')
self.geometry("450x450")
self.resizable(0, 0)
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 F in (page_Menu, page_Training, page_Quizzes, page_Mgmt, page_Roster):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("page_Menu")
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
# frame.pack(side="top", fill="both", expand=True)
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class page_Menu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
### This code is not working currently // It displays Bell Bank logo
# BellLogo = Image.open('bell1.png')
# BellLogo = BellLogo.resize((85, 85), Image.ANTIALIAS)
# renderedLogo = ImageTk.PhotoImage(BellLogo)
# LogoLabel = tk.Label(image=renderedLogo)
# LogoLabel.pack()
label = tk.Label(self, text="Bell Bank: Learning Management Software", font=controller.title_font, background="blue", foreground="white")
label.pack(side="top")
button1 = tk.Button(self, text="Training",
command=lambda: controller.show_frame("page_Training"))
button2 = tk.Button(self, text="Quizzes",
command=lambda: controller.show_frame("page_Quizzes"))
button3 = tk.Button(self, text="Management",
command=lambda: controller.show_frame("page_Mgmt"))
button1.pack(expand=1)
button2.pack(expand=1)
button3.pack(expand=1)
class page_Training(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Training To-Do, Scheduling, etc.", foreground="blue", background="lightgray")
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("page_Menu"))
button.pack()
class page_Quizzes(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Quiz Scores, Performance, etc.", foreground="blue", background="lightgray")
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("page_Menu"))
button.pack()
class page_Mgmt(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Trainer Admin: Course, Roster and Training Mgmt", foreground="blue", background="lightgray")
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("page_Menu"))
button1 = tk.Button(self, text="Training Classes/Rosters",
command=lambda: controller.show_frame("page_Roster"))
button.pack()
button1.pack()
class page_Roster(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tasks=None
super().__init__()
if not tasks:
self.tasks = []
else:
self.tasks = tasks
trainee1 = tk.Label(self, text="---Add Trainee Here---", bg="lightgrey", fg="blue", pady=10)
self.tasks.append(trainee1)
for task in self.tasks:
task.pack(side="top", fill="x")
self.task_create = tk.Text(self, height=3, bg="white", fg="black")
self.task_create.pack(side="bottom", fill="x")
self.task_create.focus_set()
self.bind("<Return>", self.add_task)
self.color_schemes = [{"bg": "lightgrey", "fg": "blue"}, {"bg": "grey", "fg": "white"}]
def add_task(self, event=None):
task_text = self.task_create.get(1.0,END).strip()
if len(task_text) > 0:
new_task = tk.Label(self, text=task_text, pady=10)
_, task_style_choice = divmod(len(self.tasks), 2)
my_scheme_choice = self.color_schemes[task_style_choice]
new_task_configure(bg=my_scheme_choice["bg"])
new_task_configure(fg=my_scheme_choice["fg"])
new_task.pack(side="top", fill="x")
self.tasks.append(new_task)
self.task_create.delete(1.0, END)
if __name__ == "__main__":
app = BellBankLMS()
app.mainloop()
Consider this code:
class page_Roster(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tasks=None
super().__init__()
Notice that you are first doing tk.Frame.__init__(self, parent), which calls the __init__ of the superclass. A couple lines later you do super().__init__() which also calls the __init__ of the superclass. Only, in this second attempt you are not passing parent to the function. Because of that, this widget is a child of the root window.
You need to do one of the following:
remove the line super().__init__(), or
remove the line tk.Frame.__init__(self, parent) and change the other line to super().__init__(parent).

Overlap different frames in Tkinter

I'm trying to make a calculator and it has different frames i.e Basic, Statistics, ..., etc. However, I'm having issues to show each frame.
This is the container for all the frames (I took a code of a previous post as example)
import tkinter as tk
class calculatorframe(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
#----------------CONTAINER FOR ALL THE FRAMES----------
container = tk.Frame(self)
container.pack()
#--------------------- DROPDOWN MENU------------------
tkvar = tk.StringVar()
choices={'Basic Mode','Calculus Mode'} #Options of the dropdown menu
tkvar.set('Basic Mode') #default frame
dropdownmenu =tk.OptionMenu(container, tkvar, *choices)
dropdownmenu.grid(row=2,column=3) #position of the dropdown menu
self.frames = {}
for F in (Basic, Calculus):
page_name = F.__name__
frame = F(parent= container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky= "nsew")
self.show_frame('Basic')
#-------FUNCTION TO SHOW THE CURRENT FRAME
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
These are the classes that I created for the basic calculator
class Basic(tk.Frame):
def __init__(self, parent, controller):
#--------------- SCREEN ---------------
tk.Frame.__init__(self, parent)
screen = tk.Entry(self, width=80)
screen.grid(row=3, column=1,columnspan=7) #position of the screen
#------------ BUTTON ---------------------
button7=tk.Button(self, text="7", width=8) #button
button7.grid(row=4,column=1)
#---------------------frame for calculus -------------------------
class Calculus(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#-----------------------------SCREEN------------
screen=tk.Entry(self, width=50)
screen.pack()
screen.grid(row=3, column=1, pady=20, columnspan=7) #position of the screen
#------------------------BUTTON---------------
go=tk.Button(self, height=1, text="Go") #button
go.grid(row=1, column=8)
if __name__ == "__main__":
app = calculatorframe()
app.mainloop()
I'm aware that I have to keep track of the value of tkvar and that I need to do it using trace() and pass that value to show_frame, however, I don't know where to place it in my code. I tried to put it below the dropdown menu, but I get an error message and I tried after the function show_frame and it did not work either. I'm a bit stuck, I would really appreciate your help, thanks in advance.
The simple solution would be to add a command to your OptionsMenu() function. We will also need to change your class names and your choice options due to how the command argument works here.
For the OptionsMenu() command argument when you tell it to call a method it will automatically pass the value of the selected item in the drop down. So because of this we need to make sure our selection reflect the class names. You can change the choices/classes to be whatever you wish I just used BasicMode and CalculusMode as an example.
The command will automatically pass the value selected so we can use that to call each frame using you show_frame method.
Take a look at the below code and let me know if you have any questions.
import tkinter as tk
class calculatorframe(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack()
tkvar = tk.StringVar()
choices = {'BasicMode', 'CalculusMode'}
tkvar.set('BasicMode')
dropdownmenu = tk.OptionMenu(container, tkvar, *choices, command=self.show_frame)
dropdownmenu.grid(row=2, column=3)
self.frames = {}
for F in (BasicMode, CalculusMode):
page_name = F.__name__
frame = F(parent= container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame('BasicMode')
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class BasicMode(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
screen = tk.Entry(self, width=80)
screen.grid(row=3, column=1, columnspan=7)
button7 = tk.Button(self, text="7", width=8)
button7.grid(row=4,column=1)
class CalculusMode(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
screen = tk.Entry(self, width=50)
screen.pack()
screen.grid(row=3, column=1, pady=20, columnspan=7)
go = tk.Button(self, height=1, text="Go")
go.grid(row=1, column=8)
if __name__ == "__main__":
app = calculatorframe()
app.mainloop()

(tkinter) Why aren't my variables being displayed using labels?

I'm trying to write a program which takes the users information, like their name and stuff, on one page, and then displays these entries on another. I'm using Tkinter and I can't get their entries to display on the other page. Here's the program:
import tkinter as tk
from tkinter import ttk
#PROFILE VARS
FirstName = ('none')
#INITIALIZING
class MegaQuiz(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "THE MEGA POP QUIZ")
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 F in (ProfilePage, MainPage):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("ProfilePage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
#PROFILE PAGE
class ProfilePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
global FirstName
#Profile Title
profile_title = tk.Label(self, text="Create A Profile Yo")
profile_title.grid(column=0, row=2)
#FIRST NAME
Q1_title = tk.Label(self, text="First Name:")
Q1_title.grid(column=0, row=1)
FirstNameEntry = tk.Entry(self)
FirstNameEntry.grid(column=2, row=4)
FirstName = str(FirstNameEntry.get())
#NEXT BUTTON
Button1 = tk.Button(self, text="NEXT",
command = lambda: controller.show_frame("MainPage"))
Button1.grid(column=10, row=10)
#MAIN MENU PAGE
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
#Play BUTTON
PlayBTN = tk.Button(self, text="PLAY", width=40)
PlayBTN.grid(column=0, row=20, sticky="nesw")
#ProfileDisplay
FirstNameDis = tk.Label(self, text=('FirstName: ' + FirstName))
FirstNameDis.grid(column=0, row=0, sticky="w")
#RUNNING PROGRAM
app = MegaQuiz()
app.mainloop()
The problem is that it displays the "FirstName: ", but doesn't display the variables FirstName, just blankness, help.
The quickest way to fix this is to move your FirstName variable to the MegaQuiz as a class attribute and then use it from there. We can change your NEXT button command to call a class method and then from that method update the FirstName variable and then also set the FirstNameDis label text from that same method.
First move the FirstName variable into your MegaQuiz class by putting this line in the __init__ section.
self.FirstName = 'none'
Then change this:
#NEXT BUTTON
Button1 = tk.Button(self, text="NEXT", command = lambda: controller.show_frame("MainPage"))
To this:
#NEXT BUTTON
Button1 = tk.Button(self, text="NEXT", command=self.next_button)
Button1.grid(column=10, row=10)
def next_button(self):
self.controller.FirstName = self.FirstNameEntry.get()
self.controller.frames["MainPage"].FirstNameDis.config(text='FirstName: ' + self.controller.FirstName)
self.controller.show_frame("MainPage")
In your MainPage change this:
self.FirstNameDis = tk.Label(self, text='FirstName: ' + FirstName)
To this:
self.FirstNameDis = tk.Label(self, text='FirstName: ' + self.controller.FirstName)
That should be all you need to fix this.
I did notice a few PEP8 issues so here is your code rewritten to provide a fix to your problem and also to rewrite some things to better follow the PEP8 guidelines.
Not sure why you are adding () to some of your string variables but it is not needed.
variable and class attribute names should be all lower case with underscores to between words.
You do not need to provide a variable name for everything. If you have a button or a label you know you will not be updating later then you can write them without the variable names.
Code:
import tkinter as tk
class MegaQuiz(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self)
self.title("THE MEGA POP QUIZ")
self.first_name = 'none'
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 F in (ProfilePage, MainPage):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("ProfilePage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class ProfilePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Label(self, text="Create A Profile Yo").grid(column=0, row=2)
tk.Label(self, text="First Name: ").grid(column=0, row=1)
self.fn_entry = tk.Entry(self)
self.fn_entry.grid(column=2, row=4)
tk.Button(self, text="NEXT", command=self.next_button).grid(column=10, row=10)
def next_button(self):
self.controller.first_name = self.fn_entry.get()
self.controller.frames["MainPage"].fn_dis.config(text='FirstName: {}'.format(self.controller.first_name))
self.controller.show_frame("MainPage")
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Button(self, text="PLAY", width=40).grid(column=0, row=20, sticky="nesw")
self.fn_dis = tk.Label(self)
self.fn_dis.grid(column=0, row=0, sticky="w")
app = MegaQuiz()
app.mainloop()

Notebook with Multiple Frames

I am trying to make a tkinter widow with multiple frames, but also the functions of notebook, like multiple widows. The problem is I am kind of unfamiliar with tkinter and am not sure how to do that. This is my current code, and it doesn't work, and would love to know what I should do to make it work. Again, the dream end result would be that I would have a first widow, which says the test text, and then the 2nd window which has multiple tabs.
from tkinter import ttk
import tkinter as tk
Font= ("Verdana", 8)
LargeFont = ("Verdana", 12)
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
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 F in (StartPage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Info", font=LargeFont)
label.pack(pady=2,padx=10)
text = tk.Label(self, text="testtestestetetqwegfegeg\ntestwegwegwegweg", font=Font)
text.pack(pady=2,padx=2)
button = tk.Button(self, text="Go to the Card",
command=lambda: controller.show_frame(PageOne))
button.pack(fill="x")
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
nb = ttk.Notebook(ttk.Frame())
nb.grid(row=1, column=0, columnspan = 50, rowspan=49, sticky='nesw')
p1 = (nb)
nb.add(p1, text='test')
label = tk.Label(self, text="", font=LargeFont)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
app = App()
app.mainloop()
The error that I eventually get is that it creates a third frame that is displayed with the test tab. Everything else works.
Thanks for your help
I know exactly what you mean because I'm trying the same. To me
nb = ttk.Notebook(self)
worked.
best
Pkanda
Taubate Brazil

Accessing variables from different frames tkinter using 'shared_data' method

So this is a continuation of the question that I asked here: How to access user selected file across frames, tkinter
Where I was directed towards the this solution: How to access variables from different classes in tkinter python 3
This is how my code looks currently, there are two functions on page two in my attempts to get the chosen file onto the second page.
import pandas as pd
import tkinter as tk
from tkinter import filedialog
class GUI(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "GUI")
self.shared_data = {
"filename": tk.StringVar(),
}
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 F in (Page1, Page2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Page1)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class Page1(tk.Frame):
def __init__(self, parent, controller):
self.controller = controller
tk.Frame.__init__(self,parent)
ftypes = [
('CSV files','*.csv')
]
def browsefunc2():
filename = tk.filedialog.askopenfilename(filetypes=ftypes)
pathlabel.config(text=filename)
print(filename)
browsebutton = tk.Button(self, text="Browse", command=browsefunc2, height=1, width=10)
browsebutton.pack()
pathlabel = tk.Label(self)
pathlabel.pack()
button = tk.Button(self, text="Page 2",
command=lambda: controller.show_frame(Page2))
button.pack()
class Page2(tk.Frame):
def __init__(self, parent, controller):
self.controller = controller
tk.Frame.__init__(self,parent)
#method one
def print_df():
#print(self.controller.shared_data["filename"].get())
df = pd.read_csv(self.controller.shared_data["filename"].get())
print(df)
#method two
filename__ = tk.Entry(self, textvariable=self.controller.shared_data["filename"])
def print_df2():
#print(filename__)
df = pd.read_csv(filename__)
print(df)
button1 = tk.Button(self, text="Print DF 1", command=print_df)
button1.pack()
button2 = tk.Button(self, text="Print DF 2", command=print_df2)
button2.pack()
button3 = tk.Button(self, text="Page 1",
command=lambda: controller.show_frame(Page1))
button3.pack()
app = GUI()
app.mainloop()
However when trying to use the 'tk.Entry' method to get the variable "filename" in Page2, I am faced with the error ".!frame.!page2.!entry" for 'print' and "ValueError: Invalid file path or buffer object type: " for 'read_csv()'.
Alternatively, when trying to use the '.get()' method, I am faced with the error "FileNotFoundError: File b'' does not exist" for both instances
I appreciate that these are several errors for a single question but all I need is one method to work. I have no idea why the solution mentioned above hasn't worked with my code considering it's an almost identical problem.
Any tips would be useful.

Categories

Resources