【问题标题】:tkinter treeview open state is not up to date when callback is triggered触发回调时,tkinter 树视图打开状态不是最新的
【发布时间】:2021-09-30 06:58:28
【问题描述】:

我目前正在开发一个 tkinter 应用程序,该应用程序使用树视图元素在层次结构中显示数据。在此应用程序的一部分中,我需要更新项目的数据。不幸的是,获取这些数据很昂贵(时间和处理上),所以我现在只更新当前可见的项目。

我遇到的问题是,当我将(左键单击)事件绑定到一个项目,然后在树视图中查询打开的项目以尝试确定可见的内容时,会返回以前打开的项目,但当前打开的项目是不是(直到单击后续项目)。

我看到this question关于查询(和设置)打开状态,但它似乎不能满足我的需求。

我有以下简化的代码,它演示了这个问题:

## import required libraries
import tkinter
import tkinter.ttk
import random
import string

## event handler for when items are left clicked
def item_clicked(event):        
    tree = event.widget
    
    ## we assume event.widget is the treeview    
    current_item = tree.item(tree.identify('item', event.x, event.y))
    print('Clicked ' + str(current_item['text']))
    
    ## for each itewm in the treeview
    for element in tree.get_children():    
        ## if it has elements under it..
        if len(tree.get_children(element)) > 0:
            ## get the element name
            element_name = tree.item(element)['text']
            ## check if it is open
            if tree.item(element)['open'] is True:
                print('Parent ' + element_name + ' is open')
            else:
                print('Parent ' + element_name + ' is closed')
 
## make the window and treeview
root = tkinter.Tk()
root.title('Treeview test')
tree = tkinter.ttk.Treeview(root, selectmode = 'browse', columns = ('num', 'let'))
tree.heading('#0', text = 'Name')
tree.heading('num', text = 'Numbers')
tree.heading('let', text = 'Letters')
tree.bind('<Button-1>', item_clicked)
tree.pack()

## populate the treeview with psuedo-random data
parents = ['']
for i in range(100):
    id = str(i)
    ## higher probability that this won't be under anything
    if random.randrange(50) > 40:
        parent = random.choice(parents)
    else:
        parent = ''
        
    ## make up some data
    tree.insert(parent, 'end', iid = id, text = 'Item ' + id)
    tree.set(id, 'num', ''.join(random.choices(string.digits, k=10)))
    tree.set(id, 'let', ''.join(random.choices(string.ascii_uppercase, k=10)))
    
    parents.append(id)

## main event loop (blocking)    
root.mainloop()

此代码将生成一个随机层次结构中包含 100 个项目的树视图。单击任何项​​目将打印具有子项且当前已展开(打开)的项目列表。与我的主要代码一样,问题是没有报告最新打开的项目(即落后了一步)。

在查询其状态之前(在 item_clicked 函数的开头)将 update() 添加到树视图并不能解决问题。

  • 如何在上面代码的事件处理程序中准确获取项目的打开状态?
  • 在项目实际展开(打开)之前触发事件是否存在问题,如果是,为什么 update() 不能解决此问题?
  • 是否存在可供树视图小部件返回当前可见项目列表的替代函数?

在 Windows 10 上运行 Python 3.7.3(Tk 版本 8.6.9)。

【问题讨论】:

  • 您是否尝试绑定到&lt;&lt;TreeviewOpen&gt;&gt; 和/或&lt;&lt;TreeviewSelect&gt;&gt;
  • 绑定&lt;ButtonRelease-1&gt;&lt;&lt;TreevewSelect&gt;&gt; 而不是&lt;Button-1&gt;(与&lt;ButtonPress-1&gt; 相同)。
  • > 和 都解决了跟踪打开状态的问题,但只有后者似乎将树视图传递给 event.widget

标签: python tkinter treeview


【解决方案1】:

将上述代码中的事件绑定从 &lt;Button-1&gt; 更改为 &lt;ButtonRelease-1&gt; 可解决此问题。

在上面的代码中应该注意的是,打开/关闭状态只会为没有父项的子项打印(即它不会下降到树中)。要解决此问题,您只需对每个带有子项的项目递归调用 tree.get_children(item_id)

【讨论】:

    猜你喜欢
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    相关资源
    最近更新 更多