In the code below, I have a Treeview and a button. Whenever an item in the Treeview is selected, I want the button to appear, when ever the button is pressed, I want to deselect the selected Treeview item, and then have the button disappear.
This almost works. What is happening is the Treeview selection is deselected whenever the button is pressed, but it does not disappear. If the button is then pressed a second time (with nothing selected in the Treeview) it will disappear.
When I was debugging this I can see that the table_row_selected
function would be called when the clear_selection
function ran. I assume this has something to do with the table.selection_remove
activating the binding on table
Any ideas how I could get this functionality to work?
import tkinter as tk
from tkinter import ttk
# Whenever a table row is selected, show the 'clear_button'
def table_row_selected(clear_button):
clear_button.grid(column=0, row=1)
# Whenver clear_button is clicked, clear the selections from the
# table, then hide the button
def clear_selection(table, clear_button):
for i in table.selection():
table.selection_remove(i)
clear_button.grid_forget()
root = tk.Tk()
content = ttk.Frame(root)
table = ttk.Treeview(content)
# Create clear_button, call configure to assign command that hides clear_button
clear_button = ttk.Button(content, text='Clear')
clear_button.configure(command=lambda: clear_selection(table, clear_button))
# Setup table columns
table['columns'] = 'NAME'
table.heading('NAME', text='Name')
# Layout widgets
content.grid(column=0, row=0)
table.grid(column=0, row=0)
# Bind selection to tree widget, call table_row_selected
table.bind('<<TreeviewSelect>>', lambda event: table_row_selected(clear_button))
# Fill in dummy data
for i in ['one', 'two', 'three']:
table.insert('', tk.END, values=i)
root.mainloop()
CodePudding user response:
Based on the document on <<TreeviewSelect>>
:
<<TreeviewSelect>>
Generated whenever the selection changes.
So the callback will be executed whenever selection changes, either item is selected or deselected. So when you clear all selection, the callback will be executed and the button will be shown.
You need to check whether there is item selected inside table_row_selected()
to determine whether to show the button:
def table_row_selected(clear_button):
if table.selection():
clear_button.grid(column=0, row=1)
If you want to pass the treeview as an argument, you need to change the definition of the function and how the function is called:
def table_row_selected(table, clear_button):
if table.selection():
clear_button.grid(column=0, row=1)
...
table.bind('<<TreeviewSelect>>', lambda event: table_row_selected(event.widget, clear_button))
...
Note that you can use
table.selection_set('')
to replace:
for i in table.selection():
table.selection_remove(i)