【问题标题】:Python Treeview alternate row colouring after sorting排序后的Python Treeview交替行着色
【发布时间】:2021-10-30 08:56:10
【问题描述】:

有没有办法在排序后保持替代行着色?我的树视图有 2,000 多行,并且想知道除了每次对列进行排序时重新标记所有行之外是否有任何解决方案。当您单击任何列时,行颜色会混淆。

环境:Python 3.10.0 Windows 21H1

import tkinter as objTK
from tkinter import ttk as objTTK
from functools import partial

# Custom column sort for treeview
class MyTreeview(objTTK.Treeview):
    def heading(self, column, sort_by=None, **kwargs):
        if sort_by and not hasattr(kwargs, 'command'):
            func = getattr(self, f"_sort_by_{sort_by}", None)
            if func:
                kwargs['command'] = partial(func, column, False)
            # End of if
        # End of if
        return super().heading(column, **kwargs)
    # End of heading()

    def _sort(self, column, reverse, data_type, callback):
        l = [(self.set(k, column), k) for k in self.get_children('')]
        l.sort(key=lambda t: data_type(t[0]), reverse=reverse)
        for index, (_, k) in enumerate(l):
            self.move(k, '', index)
        # End of for loop
        self.heading(column, command=partial(callback, column, not reverse))
    # End of _sort()

    def _sort_by_name(self, column, reverse):
        self._sort(column, reverse, str, self._sort_by_name)
    # End of _sort_by_num()
# End of class MyTreeview

objWindow = objTK.Tk()

arrlbHeader = ["Type" , "Description"]
treeview = MyTreeview(columns=arrlbHeader, show="headings")
arrRows = [
    ["Expenses", "Gen"],
    ["Expenses", "Aug"],
    ["Expenses", "Aug"],
    ["Income", "Aug"],
    ["Expenses", "Aug"]
]
arrColWidth = [70, 80]
arrColAlignment = ["center", "e"]

# Column header and attributes
arrSortType = ["name", "name"]
for iCount in range(len(arrlbHeader)):
    strHdr = arrlbHeader[iCount]
    treeview.heading(strHdr, text=strHdr.title(), sort_by=arrSortType[iCount])
    treeview.column(arrlbHeader[iCount], width=arrColWidth[iCount], stretch=True, anchor=arrColAlignment[iCount])
# End of for loop

treeview.pack()

# Row colouring tags
treeview.tag_configure("tgOddRow", background="white")
treeview.tag_configure("tgEvenRow", background="blue")      

# Insert rows
for iCount in range(len(arrRows)):
    if iCount % 2 == 0:
        treeview.insert("", "end", values=arrRows[iCount], tags="tgEvenRow")
    else:
        treeview.insert("", "end", values=arrRows[iCount], tags="tgOddRow")
# End of for loop

objWindow.bind("<Escape>", lambda funcWinSer: objWindow.destroy())

objWindow.mainloop()

【问题讨论】:

  • 重新标记似乎是唯一的解决方案,IMO
  • 您可以使用您喜欢的值配置它们,而不是移动您的列。
  • 为什么不想重新标记行?
  • @Atlas435 猜猜这和重新标记是一样的
  • @BryanOakley 除了重新标记之外,您建议如何解决我发布的问题?

标签: python-3.x tkinter


【解决方案1】:

解决方案是重新标记所有项目。树视图小部件可以在几分之一秒内重新标记几千行。

这是一个简单的例子。它假定您没有嵌套在其他项目下的项目。如果你这样做了,那么说明这一点相当简单。

def retag():
    tag = "tgOddRow"
    for iid in treeview.get_children(""):
        tag = "tgOddRow" if tag == "tgEvenRow" else "tgEvenRow"
        treeview.item(iid, tags=(tag,))

当我在具有 10,000 行的树视图上运行该函数时,它需要不到 100 毫秒。

【讨论】:

    猜你喜欢
    • 2011-12-14
    • 2020-12-30
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 2011-01-19
    • 2010-09-06
    相关资源
    最近更新 更多