Here is a simplified version of some code that I have. In the first frame, the user selects a csv file using 'tk.filedialog' and it is meant to be plotted on the same frame on the canvas.
There is also a second frame that is capable of plotting the graph in case it is easier to do it across a different frame.
Running this version of the code results in the error: "ValueError: Invalid file path or buffer object type: ". I am not sure how to get this code to work without this problem occurring, so that the user selected file plots on the empty graph with columns 'a' and 'b'.
import csv
import pandas as pd
import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
from tkinter import messagebox
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
fig = Figure(figsize=(5,4), dpi=100)
ax= fig.add_subplot(111)
LARGE_FONT= ("Verdana", 12)
class GUI(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "GUI")
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 (Home, Graph):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Home)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class Home(tk.Frame):
def __init__(self, parent, controller):
self.controller = controller
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10, padx=10)
ftypes = [
('CSV files','*.csv')
]
def browsefunc2():
filename = tk.filedialog.askopenfilename(filetypes=ftypes)
pathlabel2.config(text=filename)
filename = filename.get()
return filename
#this line is just used to check that hard-coding in a filename works, which it does providing 'filename = tk.StringVar()' is removed
#filename = '...'
filename = tk.StringVar()
df = pd.read_csv(filename, encoding='latin-1')
browsebutton = tk.Button(self, borderwidth=0, text="Browse", command=browsefunc2, height=1, width=10)
browsebutton.pack()
pathlabel2 = tk.Label(self, borderwidth=0)
pathlabel2.pack()
canvas = FigureCanvasTkAgg(fig, self)
df.plot.scatter('a', 'b', ax=ax)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
button2 = ttk.Button(self, text="Graph",
command=lambda: controller.show_frame(Graph))
button2.pack()
class Graph(tk.Frame):
def __init__(self, parent, controller):
self.controller = controller
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Graph", font=LARGE_FONT)
label.pack(pady=10,padx=10)
canvas = FigureCanvasTkAgg(fig, self)
#this line causes a problem as the dataframe is not recognised across frames
df.plot.scatter('a', 'b', ax=ax)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
button3 = ttk.Button(self, text="Back",
command=lambda: controller.show_frame(Home))
button3.pack()
app = GUI()
app.mainloop()
As far as I'm aware it's not possible to upload a .csv file onto StackOverflow so I have recreated an example one, but the file type needs to be .csv.
a,b
1,10
2,32
3,23
4,5
5,4
6,66
7,7
8,19
9,31
10,44
I haven't run your 'simplified' version of the code because it's by no means a Minimal, Complete, and Verifiable example.
The error tells you that you're assuming something is a path or buffer when it is StringVar
. I believe the error is on the line:
df = pd.read_csv(filename, encoding='latin-1')
this requires filename
to be a path or buffer object where as on the very line above filename
is indeed a StringVar
object:
filename = tk.StringVar()
df = pd.read_csv(filename, encoding='latin-1')
In order to reach the value of StringVar
or any of the Variable subclass types, one needs to use get
method.
filename.get()
However, that would result an empty string, ''
which would raise another error.