I'm trying to read the content from a CSV file and create a setup window in which I can set new values in the radiobuttons and save them. For this, I've created a loop which creates N-1
rows from a CSV whose content is:
Row0;T
Row1;M
Row2;-
Row3;C
Row4;O
The problem is than when I try to get a new value by clicking a different radio button, I don't get that value. I've tried using the methods select, invoke, creating a function which prints what's selected, but nothing returns the correct value.
I think the problem is between lines 44 and 88
import pandas as pd
import os
from tkinter import *
import tkinter as tk
from tkinter import ttk
import platform
class Application(ttk.Frame):
def __init__(self):
root = Tk()
root.geometry("555x490")
root.resizable(0,0)
self.notebook = ttk.Notebook(root)
self.notebook.grid(sticky='news')
self.notebook.pressed_index = None
self.container = Frame(self.notebook)
self.container.grid(sticky='news')
self.notebook.add(self.container)
self.canvas = Canvas(self.container, width=530, height=470)
self.scroll = Scrollbar(self.container, command=self.canvas.yview)
self.canvas.config(yscrollcommand=self.scroll.set, scrollregion=(0,0,100,1000))
self.canvas.grid(row=0, column=0, sticky="news")
self.scroll.grid(row=0, column=1, sticky='ns')
self.frame = Frame(self.canvas, width=555, height=1000)
self.canvas_window = self.canvas.create_window(555, 500, window=self.frame)
self.container.bind("<Configure>", self.onFrameConfigure) #bind an event whenever the size of the container frame changes.
self.canvas.bind("<Configure>", self.onCanvasConfigure) #bind an event whenever the size of the canvas frame changes.
self.container.bind('<Enter>', self.onEnter) # bind wheel events when the cursor enters the control
self.container.bind('<Leave>', self.onLeave) # unbind wheel events when the cursorl leaves the control
self.onFrameConfigure(None) #perform an initial stretch on render, otherwise the self.scroll region has a tiny border until the first resize
archive = pd.read_csv(os.getcwd() "\\test.csv", sep=';', engine='python')
y=0
self.radioInbound = []
self.radioInbound1 = []
self.radioInbound2 = []
self.radioInbound3 = []
self.radioInbound4 = []
for self.element in range(len(archive.index)):
y =20
# El nombre de cada fila
self.label = tk.Label(self.frame, text=(str(self.element 1) ' - ' archive.iloc[self.element,0])).grid(column=20, row=y)
# Radio buttons para seleccionar el valor
self.radioInbound.append(tk.IntVar())
#print(self.radioInbound)
if archive.iloc[self.element,1] == 'M':
self.radioInbound[self.element].set(1)
elif archive.iloc[self.element,1] == 'C':
self.radioInbound[self.element].set(2)
elif archive.iloc[self.element,1] == 'O':
self.radioInbound[self.element].set(3)
else:
self.radioInbound[self.element].set(4)
# Pinta los 4 radiobutton por cada self.elemento existente en el inbound
self.radioInbound1.append(tk.Radiobutton(self.frame, text='M', variable=self.radioInbound[self.element], value=1, command=self.selected()))
self.radioInbound1[self.element].grid(column=280,row=y)
self.radioInbound2.append(tk.Radiobutton(self.frame, text='C', variable=self.radioInbound[self.element], value=2, command=self.selected()))
self.radioInbound2[self.element].grid(column=310,row=y)
self.radioInbound3.append(tk.Radiobutton(self.frame, text='O', variable=self.radioInbound[self.element], value=3, command=self.selected()))
self.radioInbound3[self.element].grid(column=340,row=y)
self.radioInbound4.append(tk.Radiobutton(self.frame, text='-', variable=self.radioInbound[self.element], value=4, command=self.selected()))
self.radioInbound4[self.element].grid(column=370,row=y)
#print(self.radioInbound1)
# Mira el valor de cada celda para invocar el radiobutton correspondiente
#if archive.iloc[self.element,1] == 'M':
# self.radioInbound1[self.element].select() ##hay que invocar al que esté en cada momento en el archivo csv
#elif archive.iloc[self.element,1] == 'C':
# self.radioInbound2[self.element].select()
#elif archive.iloc[self.element,1] == 'O':
# self.radioInbound3[self.element].select()
#else:
# self.radioInbound4[self.element].select()
#print(self.radioInbound)
root.mainloop()
def selected(self):
#print(self.radioInbound[self.element].get())
pass
def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox("all")) #whenever the size of the frame changes, alter the self.scroll region respectively.
def onCanvasConfigure(self, event):
'''Reset the canvas window to encompass inner frame when required'''
canvas_width = event.width
self.canvas.itemconfig(self.canvas_window, width = canvas_width) #whenever the size of the canvas changes alter the window region respectively.
def onm ouseWheel(self, event): # cross platform self.scroll wheel event
if platform.system() == 'Windows':
self.canvas.yview_scroll(int(-1* (event.delta/120)), "units")
elif platform.system() == 'Darwin':
self.canvas.yview_scroll(int(-1 * event.delta), "units")
else:
if event.num == 4:
self.canvas.yview_scroll( -1, "units" )
elif event.num == 5:
self.canvas.yview_scroll( 1, "units" )
def onEnter(self, event): # bind wheel events when the cursor enters the control
if platform.system() == 'Linux':
self.canvas.bind_all("<Button-4>", self.onMouseWheel)
self.canvas.bind_all("<Button-5>", self.onMouseWheel)
else:
self.canvas.bind_all("<MouseWheel>", self.onMouseWheel)
def onLeave(self, event): # unbind wheel events when the cursorl leaves the control
if platform.system() == 'Linux':
self.canvas.unbind_all("<Button-4>")
self.canvas.unbind_all("<Button-5>")
else:
self.canvas.unbind_all("<MouseWheel>")
app = Application()
CodePudding user response:
You have used same instance variable self.element
in the for loop of creating those radiobuttons. So after the for loop, self.element
will refer to the last item of self.radioInbound
.
Actually the instance variable self.element
is not necessary. And you need to pass the corresponding index to self.selected()
for those radiobuttons using default value of lambda
assigned to command
option when creating those radiobuttons:
### actually don't need to inherited from ttk.Frame ###
#class Application(ttk.Frame):
class Application:
def __init__(self):
...
# just use a local variable instead of instance variable
for idx in range(len(archive.index)):
y =20
# El nombre de cada fila
self.label = tk.Label(self.frame, text=(str(idx 1) ' - ' archive.iloc[idx,0])).grid(column=20, row=y)
# Radio buttons para seleccionar el valor
self.radioInbound.append(tk.IntVar())
#print(self.radioInbound)
if archive.iloc[idx,1] == 'M':
self.radioInbound[idx].set(1)
elif archive.iloc[idx,1] == 'C':
self.radioInbound[idx].set(2)
elif archive.iloc[idx,1] == 'O':
self.radioInbound[idx].set(3)
else:
self.radioInbound[idx].set(4)
# Pinta los 4 radiobutton por cada idxo existente en el inbound
### used lambda with argument with default value ###
self.radioInbound1.append(tk.Radiobutton(self.frame, text='M', variable=self.radioInbound[idx], value=1, command=lambda i=idx:self.selected(i)))
self.radioInbound1[idx].grid(column=280,row=y)
self.radioInbound2.append(tk.Radiobutton(self.frame, text='C', variable=self.radioInbound[idx], value=2, command=lambda i=idx:self.selected(i)))
self.radioInbound2[idx].grid(column=310,row=y)
self.radioInbound3.append(tk.Radiobutton(self.frame, text='O', variable=self.radioInbound[idx], value=3, command=lambda i=idx:self.selected(i)))
self.radioInbound3[idx].grid(column=340,row=y)
self.radioInbound4.append(tk.Radiobutton(self.frame, text='-', variable=self.radioInbound[idx], value=4, command=lambda i=idx:self.selected(i)))
self.radioInbound4[idx].grid(column=370,row=y)
...
### added argument idx ###
def selected(self, idx):
print(idx, self.radioInbound[idx].get())
...