Reputation: 229
I am trying to create a Pandas' DataFrame GUI in tkinter that would update the moment the user changes the value of the cell (each cell is an Entry). I thought that converting the DataFrame into tkinter variables (tk.StringVar, tk.IntVar...) would be the best way to achieve that.
My problem: I am not sure how to convert dataframe into those objects. I tried using the astype function, but it doesn't seem to convert the type.
My questions: 1) how to convert dataframe into tkinter variables?
2) is converting dataframe into ttkinter variables the best way to make the dataframe update instantly?
Upvotes: 1
Views: 6693
Reputation: 142641
I think pandas
can't use StringVar
as dtype
.
You would have to get every element in dataframe and create separated var = StringVar(value=df[row,col])
(or var = StringVar() ; var.set(df[row,col]))
) and keep them in standard list.
But you could put values directly to Entry
, and bind()
event to Entry
which will execute function everytime something change in Entry
or you press Enter
. This function could copy value from Entry
to dataframe
.
EDIT: example code
It changes value in dataframe
when you click Enter
(or Enter
on keypad) in any Entry
.
import pandas as pd
import tkinter as tk
df = pd.DataFrame([[1,2,3], [5,6,7], [101,102,103]])
# --- functions ---
def change(event, row, col):
# get value from Entry
value = event.widget.get()
# set value in dataframe
df.iloc[row,col] = value
print(df)
# --- main --
root = tk.Tk()
# create entry for every element in dataframe
rows, cols = df.shape
for r in range(rows):
for c in range(cols):
e = tk.Entry(root)
e.insert(0, df.iloc[r,c])
e.grid(row=r, column=c)
# ENTER
e.bind('<Return>', lambda event, y=r, x=c: change(event,y,x))
# ENTER on keypad
e.bind('<KP_Enter>', lambda event, y=r, x=c: change(event,y,x))
# start program
root.mainloop()
To change value in dataframe with every key press use <KeyRelease>
(it works when you press Ctrl+V
too, so you can paste data from clipboard)
for r in range(rows):
for c in range(cols):
e = tk.Entry(root)
e.insert(0, df.iloc[r,c])
e.grid(row=r, column=c)
e.bind('<KeyRelease>', lambda event, y=r, x=c: changed(event, y,x))
EDIT: example as class DataFrameEdit(tk.Frame)
Upvotes: 4