tksheet
tksheet copied to clipboard
[Question] Edition popup window
Hi Ragarder, I would like to have your point of view if it is possible. I want to create a popup windows to edit a cell, for that I'm using extra binding : begin_edit_cell and en_edit_cell
In my application the popup windows is more complex but in the code example below, I simplified to a simple entry to reproduce the problem I have. 1 - when you double clic on one cell of the column2 a popup window appear (good) you can change the value 2 - but then I do not find the correct sequence to refresh the sheet with the new value (if you press Escape the new value appears)
I tested many internal function of tksheet to escape the text_editor cell
Do you see a better way to do it ? it seems to be a problem of focus on the cell, but I do not find how to avoid it. You can see some of my tests in comment in the ok_cb() callback (the set_cell_data and set_all_cell_sizes_to_text seems to work properly)
Thank you for your help
#!/usr/bin/env python3
import tkinter as tk
from tksheet import Sheet
root = tk.Tk()
frame = tk.Frame(root)
def end_edit_cell(event):
"""
binding function
row = event[0] / col = event[1]
"""
row = event[0]
col = event[1]
print("++> end edit: " + str(row) + "," + str(col) + " -> " + sheet.get_cell_data(row, col))
def begin_edit_cell(event):
"""
binding function
row = event[0] / col = event[1]
"""
print("++> begin edit")
row = event[0]
col = event[1]
col_name = sheet.headers()[col]
# Popup window only on col2
if col_name == 'col2':
win = tk.Toplevel(root)
x = root.winfo_rootx() + 20
y = root.winfo_rooty() + 20
win.geometry("+{}+{}".format(x, y))
win.transient(root)
win.grab_set()
win.deiconify()
f = tk.Frame(win, width=200, height=200)
f.pack(fill=tk.BOTH, expand=tk.YES, padx=10, pady=10)
value = tk.StringVar()
e = tk.Entry(f, textvariable=value)
e.pack()
value.set(data[row][col])
fbutton = tk.Frame(f, padx=10, pady=10)
fbutton.pack(fill=tk.X, expand=tk.YES)
b0 = tk.Button(
fbutton,
text="Ok",
width=15,
command=lambda win=win, row=row, col=col, value=value: ok_cb(win, row, col, value),
)
b0.pack(side=tk.RIGHT)
b1 = tk.Button(
fbutton,
text="Cancel",
width=15,
command=lambda win=win: cancel_cb(win),
)
b1.pack(side=tk.RIGHT)
f.wait_window(win)
def ok_cb(win, row, col, value):
print("++> OK try to set value: " + str(row) + "," + str(col) + " " + str(value.get()))
#sheet.set_text_editor_value(text=str(value.get()), r=row, c=col)
sheet.set_cell_data(row, col, value=value.get())
sheet.set_all_cell_sizes_to_text()
win.destroy()
#sheet.deselect("all")
#sheet.event_generate("<Escape>", when="now")
sheet.MT.destroy_text_editor("Escape")
#sheet.destroy_text_editor()
#a = sheet.MT.get_text_editor_value((row, col, "Escape"))
#print("++> OK : " + str(a))
def cancel_cb(win):
print("++> CANCEL")
win.destroy()
# ----------------------------------------------------------------------------
# Main program
# ----------------------------------------------------------------------------
if __name__ == "__main__":
data = [
["aaaa", "aaaa", "aa"],
["bbbbb", "bb", "b"],
["ccc", "ccc", "ccc"],
["dddddd", "ddd", "dddddddd"],
["xxx", "xxx", "xxx"]
]
sheet = Sheet(frame,
data=data,
headers=["col1", "col2", "col3"],
)
sheet.pack(expand=tk.YES, fill=tk.BOTH)
sheet.enable_bindings(
(
"single_select", # "single_select" or "toggle_select"
"arrowkeys",
"edit_cell",
)
)
sheet.extra_bindings("begin_edit_cell", begin_edit_cell)
sheet.extra_bindings("end_edit_cell", end_edit_cell)
sheet.set_all_cell_sizes_to_text() # cell resizing moved here
frame.pack(fill=tk.BOTH, expand=tk.YES)
root.mainloop()
Sorry for the noise, I asked you few month ago to add a try/catch on extra_binding functions and you did it (I forgot that) this is solving this issue.
by adding a raise in the begin_edit_cell function when the popup windows is closed all is done properly here below the correction
#!/usr/bin/env python3
import tkinter as tk
from tksheet import Sheet
root = tk.Tk()
frame = tk.Frame(root)
def end_edit_cell(event):
"""
binding function
row = event[0] / col = event[1]
"""
row = event[0]
col = event[1]
print("++> end edit: " + str(row) + "," + str(col) + " -> " + sheet.get_cell_data(row, col))
def begin_edit_cell(event):
"""
binding function
row = event[0] / col = event[1]
"""
print("++> begin edit")
row = event[0]
col = event[1]
col_name = sheet.headers()[col]
# Popup window only on col2
if col_name == 'col2':
win = tk.Toplevel(root)
x = root.winfo_rootx() + 20
y = root.winfo_rooty() + 20
win.geometry("+{}+{}".format(x, y))
win.transient(root)
win.grab_set()
win.deiconify()
f = tk.Frame(win, width=200, height=200)
f.pack(fill=tk.BOTH, expand=tk.YES, padx=10, pady=10)
value = tk.StringVar()
e = tk.Entry(f, textvariable=value)
e.pack()
value.set(data[row][col])
fbutton = tk.Frame(f, padx=10, pady=10)
fbutton.pack(fill=tk.X, expand=tk.YES)
b0 = tk.Button(fbutton,text="Ok", width=15,command=lambda win=win, row=row, col=col, value=value: ok_cb(win, row, col, value),)
b0.pack(side=tk.RIGHT)
b1 = tk.Button(fbutton,text="Cancel", width=15, command=lambda win=win: cancel_cb(win),)
b1.pack(side=tk.RIGHT)
f.wait_window(win)
# using raise to stop edition at begin_edit_cell level all is done in ok_cb function already
raise
def ok_cb(win, row, col, value):
print("++> OK try to set value: " + str(row) + "," + str(col) + " " + str(value.get()))
sheet.set_cell_data(row, col, value=value.get())
sheet.set_all_cell_sizes_to_text()
win.destroy()
def cancel_cb(win):
print("++> CANCEL")
win.destroy()
# ----------------------------------------------------------------------------
# Main program
# ----------------------------------------------------------------------------
if __name__ == "__main__":
data = [
["aaaa", "aaaa", "aa"],
["bbbbb", "bb", "b"],
["ccc", "ccc", "ccc"],
["dddddd", "ddd", "dddddddd"],
["xxx", "xxx", "xxx"]
]
sheet = Sheet(frame,
data=data,
headers=["col1", "col2", "col3"],
)
sheet.pack(expand=tk.YES, fill=tk.BOTH)
sheet.enable_bindings(
(
"single_select", # "single_select" or "toggle_select"
"arrowkeys",
"edit_cell",
)
)
sheet.extra_bindings("begin_edit_cell", begin_edit_cell)
sheet.extra_bindings("end_edit_cell", end_edit_cell)
sheet.set_all_cell_sizes_to_text() # cell resizing moved here
frame.pack(fill=tk.BOTH, expand=tk.YES)
root.mainloop()
@skedus, thank you for asking this question, and especially for updating it with how you fixed it! I had a very similar problem and was going crazy trying to figure out how to resolve it. Adding "break" was just the solution I was looking for.