在python Tkinter Treeview中选择多个项时出错

时间:2018-10-11 21:24:06

标签: python tkinter treeview

我的应用程序中有一个可搜索的ttk.Treeview,它根据搜索词设置选择(突出显示)。

为此,我将要选择的项目收集到以空格分隔的字符串中,如下所示:

"item_a item_b item_c"

我将此字符串传递给selection_set方法。

我遇到的问题是,即使据我所知它们具有相同的python版本(2.7.10),这在某些计算机上也无法使用。

我收到如下错误消息:

"item_a item_b item_c": Item not found

好像它正在搜索具有该巨型名称的一个物品。

我可以通过创建一个列表并对其进行遍历,然后对每个项目调用selection_add来实现相同的目标,但这要慢得多。

我想系统Tcl / Tk版本可能有所不同,可能与python安装有所不同,但是我不确定,我也不知道如何验证。

但是,即使是那样的情况,我仍然很难找到任何有关此方面的好的文档。我发现的任何文档中都没有使用空格分隔的字符串的想法,我只是在其他没有源的StackOverflow帖子中看到了使用它的想法。 (例如here

因此,我正在寻找与版本无关的(或至少是一种检测版本并执行其他操作的方法)解决方案,以使用项列表调用selection_set。如果有人能告诉我该怎么做或指向可以帮助我理解该方法的文档,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

用空格分隔的字符串起作用的原因是因为tkinter只是tcl / tk解释器的薄包装,tcl会接受以空格分隔的字符串作为列表。 set_selection将列表作为参数,因此当您将其传递为以空格分隔的字符串时,tcl将根据其内部规则拆分该字符串。

调用set_selection的正确方法是传递正确的python列表,tkinter会为您将其转换为tcl列表。

下面是一个简短的示例,该示例说明了如何通过将包含三个元素的列表传递给set_selection来选择树中的子集:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()

tree = ttk.Treeview(root)
tree.pack(fill="both", expand=True)

items = []
for i in range(10):
    item = tree.insert("", "end", text="Item {}".format(i+1))
    items.append(item)

items_to_select = items[2:5]
tree.selection_set(items_to_select)

root.mainloop()

上面的代码将导致一个如下所示的窗口:

enter image description here

答案 1 :(得分:0)

要在Python 2中使用selection_set,您需要传递一个元组来选择。您可以使用内置的tuple函数将列表轻松转换为元组。

如果您可以升级到Python 3,则可以直接使用列表,并且可能会更好。

这是一个简单的测试程序,它使用几种不同的方法在TreeView中选择项目。这应该在Python 2和3上都可以使用,因此您可以查看哪些方法可以使用。

try:
    import Tkinter as tk
    import ttk
except ImportError:
    import tkinter as tk
    import tkinter.ttk as ttk
import platform


class TestWindow:
    def __init__(self):
        self.top = tk.Tk()
        self.top.title("Test TreeView selection")
        self.top.minsize(450, 600)

        self.root_frame = ttk.Frame(self.top, padding=5)
        self.root_frame.pack(fill=tk.BOTH, expand=True)

        self.python_version_label = ttk.Label(self.root_frame, text="Python Version: " + platform.python_version())
        self.python_version_label.pack(fill=tk.X, expand=False)

        self.version_label = ttk.Label(self.root_frame, text="TCL Version: " + tk.Tcl().eval('info patchlevel'))
        self.version_label.pack(fill=tk.X, expand=False)

        self.controls_frame = ttk.Frame(self.root_frame, padding=5)
        self.controls_frame.pack(fill=tk.X, expand=False)

        self.select_space_button = ttk.Button(self.controls_frame, text="Select Space", command=self.select_space)
        self.select_space_button.pack(side=tk.LEFT, fill=tk.X, expand=True)

        self.select_loop_button = ttk.Button(self.controls_frame, text="Select Loop", command=self.select_loop)
        self.select_loop_button.pack(side=tk.LEFT, fill=tk.X, expand=True)

        self.select_list_button = ttk.Button(self.controls_frame, text="Select List", command=self.select_list)
        self.select_list_button.pack(side=tk.LEFT, fill=tk.X, expand=True)

        self.select_tuple_button = ttk.Button(self.controls_frame, text="Select Tuple", command=self.select_tuple)
        self.select_tuple_button.pack(side=tk.LEFT, fill=tk.X, expand=True)

        self.clear_button = ttk.Button(self.controls_frame, text="Clear", command=self.clear)
        self.clear_button.pack(side=tk.LEFT, fill=tk.X, expand=True)

        self.tree_frame = ttk.Frame(self.root_frame, padding=5)
        self.tree_frame.pack(fill=tk.BOTH, expand=True)

        self.tree_view = ttk.Treeview(self.tree_frame, padding=5)
        self.ysb = ttk.Scrollbar(self.tree_frame, orient='vertical', command=self.tree_view.yview)
        self.tree_view.configure(yscroll=self.ysb.set)

        self.tree_view.pack(expand=True, fill=tk.BOTH, side=tk.LEFT)
        self.ysb.pack(side=tk.RIGHT, fill=tk.Y)

        self.tree_view.heading("#0", text="Test Item")

        for i in range(0, 100):
            name = "Item " + str(i)
            item_id = self.tree_view.insert("", tk.END, str(i), text=name, open=True)
            self.tree_view.insert(item_id, tk.END, str(i) + "a", text=name + ": A")
            self.tree_view.insert(item_id, tk.END, str(i) + "b",  text=name + ": B")
            self.tree_view.insert(item_id, tk.END, str(i) + "c",  text=name + ": C")
            self.tree_view.insert(item_id, tk.END, str(i) + "d",  text=name + ": D")

        self.items = []
        for i in range(4, 41):
            self.items.append(str(i))
            self.items.append(str(i) + "a")
            self.items.append(str(i) + "b")
            self.items.append(str(i) + "d")

    def select_space(self):
        self.tree_view.selection_set(" ".join(self.items))

    def select_loop(self):
        for item in self.items:
            self.tree_view.selection_add(item)

    def select_list(self):
        self.tree_view.selection_set(self.items)

    def select_tuple(self):
        self.tree_view.selection_set(tuple(self.items))

    def clear(self):
        self.tree_view.selection_remove(self.tree_view.selection())

    def run(self):
        self.top.mainloop()


if __name__ == "__main__":
    window = TestWindow()
    window.run()

Preview

我已经在Windows 10,macOS 10.14和Debian Buster(Python 2和3)上对此进行了测试。“选择空间”在任何地方都不起作用,“选择循环”始终有效,但是速度很慢,“选择列表” ”仅适用于Python 3,“选择元组”始终有效。如果您被锁定在2.7.10中,这似乎是解决方案。