Reputation: 1247
I'm trying to implement drag and drop in tkinter treeview using the identify_element() method to indicate where I need to insert items.
When the <ButtonRelease-1>
event gets triggered I call identify_element() it returns the word "padding" and not the treeview item. I have know idea why it's not returning the item at the x/y coords like it's supposed to do.
import os
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
class App(tk.Tk):
def __init__(self, path):
super().__init__()
self.title("Ttk Treeview")
abspath = os.path.abspath(path)
self.nodes = {}
self.tree = ttk.Treeview(self)
self.tree.heading("#0", text=abspath, anchor=tk.W)
ysb = ttk.Scrollbar(self, orient=tk.VERTICAL, command=self.tree.yview)
xsb = ttk.Scrollbar(self, orient=tk.HORIZONTAL, command=self.tree.xview)
self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
self.tree.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
ysb.grid(row=0, column=1, sticky=tk.N + tk.S)
xsb.grid(row=1, column=0, sticky=tk.E + tk.W)
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.tree.bind("<<TreeviewOpen>>", self.open_node)
def button_release(e):
print('Results =', self.tree.identify_element(e.x, e.y))
self.tree.bind("<ButtonRelease-1>", button_release)
self.populate_node("", abspath)
def populate_node(self, parent, abspath):
try:
for entry in os.listdir(abspath):
entry_path = os.path.join(abspath, entry)
node = self.tree.insert(parent, tk.END, text=entry, open=False)
if os.path.isdir(entry_path):
self.nodes[node] = entry_path
self.tree.insert(node, tk.END)
except:
messagebox.showerror('Access Denied', f'Sorry you do not have access privileges for, {abspath}.')
def open_node(self, _):
item = self.tree.focus()
abspath = self.nodes.pop(item, False)
if abspath:
children = self.tree.get_children(item)
self.tree.delete(children)
self.populate_node(item, abspath)
if __name__ == "__main__":
app = App(path="/")
app.mainloop()
I expect that the output of identify_element() should return an treeview item.
Upvotes: 1
Views: 1417
Reputation: 386362
identify_element
is designed to return what part of the widget was clicked on (ie: one of the elements defined in the treeview layout), not which item you clicked on.
In tcl/tk you would use .tree identify item
rather than .tree identify element
. Oddly, tkinter doesn't provide an analogous identify_item
method. However, it does expose the generic identify
method, which can be passed "item"
as its first parameter to identify the tree item id under the cursor.
print('Results =', self.tree.identify("item", e.x, e.y))
Upvotes: 3