I'm using a function to iterate through rows of a csv (data_file) and it is intended to print the row which matches. The issue I'm seeing is that it always prints the last row from the csv instead of the matched row.
def read_ability(data_file, ability):
with open(data_file, 'r ') as f:
reader = csv.reader(f, delimiter=',')
for i in reader:
if i[0] == ability:
printout = tk.Label(output, text=i, wraplength=500, justify=tk.LEFT)
printout.pack()
The same principle used in a terminal window
def read_ability(data_file, ability):
with open(data_file, 'r ') as f:
reader = csv.reader(f, delimiter=',')
for i in reader:
if i[0] == ability:
print(i)
prints only the intended row.
I'm interpreting this result as the tkinter attempt overwriting with every row because there was a match instead of just the match. Though, I'm unsure how to correct this.
I tried putting a break statement after the pack statement to see if it would stop after the match. It made no difference.
Adding the code that is passing the arguments as initial response indicated code was functional.
def open_file(data_file):
with open(data_file, 'r ') as f:
reader = csv.reader(f, delimiter=",")
next(reader)
r = 0
c = 0
for widget in results.winfo_children():
widget.destroy()
for i in reader:
button = tk.Button(results, text=i[0], relief=tk.RIDGE, command=lambda: read_ability(data_file, i[0]))
button.grid(row=r, column=c)
c = 1
if c == 10:
r = 1
c = 0
CodePudding user response:
It all came down to how you call the function in command
. The reason it kept returning the last ability because that was the last item in the loop so that was the value that got assigned to the command
Namely, if u
is the ability then you pass the value of the button the function like this:
Button(results, text=u, relief=RIDGE,command= lambda u=u: match_values(u))
Below, I cleaned up your code a bit by separating the above into functions so that it is easier to read and follow;
This function loads the file and puts it into a list of tuples where each tuple is a row. This way you don't have to re-read the file
def load_data(data_file):
uniq_vals = []
# close off file connection before doing further stuff
with open(data_file, 'r ') as f:
# load file
reader = csv.reader(f, delimiter=",")
# convert csv to set of tuples (separate value for each column so if you have more columns, add more tuples)
datalist = [(rows[0],rows[1]) for rows in reader]
return(datalist)
This function is used to find the rows in the csv file that correspond to ability (=u
)
def match_values(u):
collection=[] # initiate container
iterate each row and collect those that match ability
for row in datalist:
if u==row[0]:
collection.append(row)
# this just prints the above into a table
ncols = len(collection[0]) # get number of columns
nrows = len(collection) # get number of rows
output = Tk()
rows = []
for i in range(nrows):
#grid with a row offset (looks prettier I think)
Label(output,text=collection[i][0]).grid(row=1 i,column=0)
Label(output,text=collection[i][1]).grid(row=1 i,column=1)
This function ultimately executes by printing the unique ability
in a grid when you press the button, it returns the rows that match that ability
.
def make_options(datalist):
# initiate list to save unique values
uniq_vals = [
# get unique ability values
uniq_vals = set(list(zip(*datalist))[1])
# initate option window
results = Tk()
r=0
c=0
offset = 0
# make grid of buttons for each unique ability
for u in uniq_vals:
print(u) # for our reference
# make button
button = Button(results, text=u, relief=RIDGE,command= lambda u=u: match_values(u))
button.grid(row=r, column=c)
c = 1
if c == 10:
r = 1
c = 0
# call the functions:
datalist = load_data(data_file)
make_options(datalist)
Cleaning Up
Currently, the above does not close existing windows so probably want to handle that.