Launch
Launch

Reputation: 35

How to make a button open a specific .csv file using Python Tkinter?

I'm trying to get this program to print the contents of a .csv file onto a GUI.

I've created in Tkinter. It mostly works, but I can't figure out a way to get each button to print the contents of the file it's linked to.

At the moment I've created a variable that links to just one of the files, which shows that it works.

The variable is "loadFiles", and the project it's set to open is "a_P.csv". Is there any way I can make the buttons link this variable to the relevant .csv file?

The code is in this pastebin link: http://pastebin.com/ZP2pPvKA

The program searches for files ending in "_P.csv" in the same folder as it, so you may have to create a .csv with 7 objects in it.

Upvotes: 3

Views: 2461

Answers (2)

Niall Byrne
Niall Byrne

Reputation: 2460

I also tried this the way heinzderaugust suggested at first:

 button[i] = ttk.Button(loadProject, text=data_files[i], command = lambda i=data_files[i]:load(i)).grid(column=1, row=i, sticky=W)  

I was also able to solve this by using a class as the intermediary part of the callback: (This class was inserted inside viewProject )

class Command:
            def __init__(self, callback, *args, **kwargs):
                    self.callback = callback
                    self.args = args
                    self.kwargs = kwargs

            def __call__(self):
                    return(self.callback(*self.args, **self.kwargs))

Then I changed your button definition to:

button[i] = ttk.Button(loadProject, text=data_files[i], command = Command(load,data_files[i])).grid(column=1, row=i, sticky=W)     

And finally I changed the load function to accept a argument:

def load(myFile):                
            spamReader = csv.reader(open(myFile))
            for row in spamReader:
                    a = list(row)

            ttk.Label(loadProject, text=(a[0])).grid(column=4, row=0, sticky=W)
            ttk.Label(loadProject, text=("\n"+a[1])).grid(column=4, row=1, sticky=W)
            ttk.Label(loadProject, text=("\n"+a[2])).grid(column=4, row=2, sticky=W)
            ttk.Label(loadProject, text=(a[3])).grid(column=4, row=3, sticky=W)
            ttk.Label(loadProject, text=(a[4])).grid(column=4, row=4, sticky=W)
            ttk.Label(loadProject, text=("\n"+a[5])).grid(column=4, row=5, sticky=W)
            ttk.Label(loadProject, text=("\n"+a[6])).grid(column=4, row=6, sticky=W)
            ttk.Label(loadProject, text=("\n\n"+a[7])).grid(column=4, row=7, sticky=W)

I am unsure which would be best practice, but both do work.

(Certainly the lambda approach does sort of seem more 'pythonic')

Source: https://code.activestate.com/recipes/66521-avoiding-lambda-in-writing-callback-functions/

Upvotes: 1

heinzderaugust
heinzderaugust

Reputation: 11

you can use a lambda function in order to pass an argument to your load function. Unfortunately pastebin ist down right now so i cannot have a look at your code. The idea is something like this:

for filename in filenames: ...Button(...,command=lambda i=filename:loadFile(i),...

so in your loadFile function you have the filename as first parameter

Upvotes: 1

Related Questions