Reputation: 303
I have created functions that can display graphs and tables of csv files in a GUI I am making with tkinter.
I have a menubar
with an import button, a plot button, and a table button. The plot and table button can successfully plot graphs and tables of csv files respectively.
What I'd like to do, is when the user selects the import button, they select a file of their choice. Then, if they happen to select the plot button, the plot function works on the file they chose from import. Moreover, if they happen to select the table button, the table function works on the file they chose from import.
I have created a file opening function called openfile()
which remembers the name of the file opened.
The problem is that I don't know how to use menubar
and openfile()
such when the import button is clicked, my application stores the filename.
Any tips on how I would go about doing this?
Here's the code I've written for the menubar
and openfile()
:
def openfile():
name= askopenfilename()
return (name[19:])
class MyApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "MyApp")
# main frame
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
# creates the menubar at the top of the window
menubar = tk.Menu(container)
# import menu for importing csv files, initializes a file opening function (tbd)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Import a CSV File", command = file_openerfunction)
menubar.add_cascade(label= "Import", menu=filemenu)
# plot menu for creating graphs and figures
Plot = tk.Menu(menubar, tearoff =0 )
Plot.add_command(label="Plot My CSV File", command= popupgraph)
menubar.add_cascade(label="Plot", menu=Plot)
# table menu for viewing data in a table
table = tk.Menu(menubar, tearoff = 0)
table.add_command(label="View MY CSV File", command = table)
table.add_cascade(label = "View Data", menu = table)
tk.Tk.config(self, menu=table)
....
....
Upvotes: 0
Views: 1212
Reputation: 4783
First of all, I would suggest you take an Object Oriented approach to split each component behaviour.
This way, you would have a class App, where you would initialise the main components of the app:
class App(tk.Tk):
def __init__(self,parent):
Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def initialize(self):
...
...
# Menubar
self.menubar = MyMenuBar(self)
# Filemenu
self.filemenu = MyFileMenu(self, menubar)
# Plot
self.plot = MyPlot(self, menubar)
# The rest for all the other components
...
def get_import_filename(self):
# Ask the child for the filename and return it
return self.filemenu.get_filename()
And then define every of your objects:
class MyPlot(tk.Menu):
def __init__(self, parent, menubar):
tk.Menu.__init__(self, menubar, tearoff=0)
self.parent = parent
self.initialize()
def initialize(self):
self.add_command(label="Plot My CSV File", command= self.popupgraph)
def popupgraph(self):
# Ask the parent for the filename
filename = self.parent.get_import_filename()
# Do whatever with the filename...like open a file
class MyFileMenu(tk.Menu):
def __init__(self, parent, menubar):
tk.Menu.__init__(self, menubar, tearoff=0)
self.parent = parent
self.initialize()
def initialize(self):
self.add_command(label="Import a CSV File", command = file_opener)
def file_opener(self):
# Your file opener function goes here
...
# At the end, save the imported file:
self.filename = filename
def get_filename(self):
return self.filename
Finally, have the main to run it:
def main():
app = App(None)
app.title('Auto login')
app.mainloop()
if __name__ == "__main__":
main()
Upvotes: 1
Reputation: 123501
I don't understand the way you were trying to do some things (or why you were doing them at all in some cases), but here's a runnable example that creates a simple Choices
cascading menu in the upper-left corner of the window of simple tkinter app. Hopefully you';; be able to adapt and integrate it into your project's code.
I made The command for importing CSV files, file_openerfunction
, a class method and have it call the openfile()
function because that way the returned value (the filename) can be store as an attribute in self.filename
. This will allow it to used in the other command choices after it is create (so they will know what file to operate upon).
try:
import Tkinter as tk
from tkFileDialog import askopenfilename
except ModuleNotFoundError: $ Python 3
import tkinter as tk
from tkinter.filedialog import askopenfilename
def openfile():
name = askopenfilename()
return name[19:]
class MyApp(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.master.title("MyApp")
self.pack(side="top", fill="both", expand=True)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
top = self.winfo_toplevel()
self.menubar = tk.Menu(top)
top['menu'] = self.menubar
self.submenu = tk.Menu(self.menubar)
self.menubar.add_cascade(label='Choices', menu=self.submenu)
self.submenu.add_command(label="Import a CSV File",
command=self.file_openerfunction)
self.submenu.add_command(label="Plot My CSV File",
command=self.popupgraph)
self.submenu.add_command(label="View MY CSV File",
command=self.table)
def file_openerfunction(self):
self.filename = openfile()
def popupgraph(self): pass
def table(self): pass
app = MyApp()
app.mainloop()
I also suggest you read and follow the PEP 8 - Style Guide for Python Code which will help standardize the code your write and improve its readability.
Upvotes: 0
Reputation: 303
otorrillas solution worked perfectly.
I found another simple way to resolve this issue. In order for the GUI to remember the file selected from import, have the file name be appended to a list. Then, call on popupgraph()
and viewcsv()
on the list element. Here's the new code for my file opening function.
file_list = []
def openfile():
name= askopenfilename()
file_list.append(name[19:])
Upvotes: 0