python:tkinter 树视图颜色未更新

python : tkinter treeview colors are not updating

这是我的第一个post,如果我的格式有误,请原谅,如果需要我会很乐意更改。

我正在使用 Tkinter 创建一个用于科学数据分析的界面。对于分子列表,四个可以在单独的图中表示。另一方面,我使用 Treeview 来显示所有分子的一些数字。 (不仅仅是显示的)当树视图行是关于显示的图时,我希望该行的文本颜色相同。

对于每个显示的图表,我在代表它的行上放置了一个不同的标签,然后使用标签方法将前景颜色更改为绘图的颜色。

代码以前工作正常,但现在我的代码没有任何更改就停止工作了。使用标签设置前景色不会改变颜色。几行之后,我也使用该方法将一行更改为粗体并且效果很好。

我设法确认代码行被正确读取:如果我将颜色设置为无法识别的值,我会在按预期执行时收到 tkinter 错误。此外,使用一些打印,if/elif 在正确的时刻按预期执行(逻辑测试中没有错误)。

该代码在另一台计算机上运行良好,这让我相信某些 python 软件包存在问题。两台电脑有相同的 ttk 版本 (0.3.1),我在注意到问题后更新了我的所有模块,以确保它不是一个过时的包。

对计算机所做的唯一更改是删除并重新安装anaconda和环境,现在在使用的环境中添加了pyinstaller的安装(使用pip)(当我在原始环境中安装pyinstaller时,我错误地修改了其他重要的软件包,不得不从头开始重新安装 anaconda 以使其再次运行)

我尝试在没有 pyinstaller 模块的情况下创建另一个相同的环境,但我得到了相同的结果。

我已经记不清有多少次我卸载并重新安装 anaconda 来解决问题了。如果可能的话,我真的很希望不必重新安装它。

我已经分离出构成树视图对象的界面代码。经过测试,下面的代码片段给了我同样的问题。

import tkinter as tk
from tkinter import ttk
import numpy as np

class Testy():
    def __init__(self, root):

        #Values set in other part of the interface
        self.Classes = ['Molecule1','Molecule2','Molecule3','Molecule4',
                        'Molecule5','Molecule6']
        self.Single_Kinetic_Menu_Var = [tk.StringVar(value = 'Molecule1'), 
                                        tk.StringVar(value = 'Molecule3'),
                                        tk.StringVar(value = 'Molecule4'), 
                                        tk.StringVar(value = 'Molecule5')]
        self.Experiment_Count = np.zeros([len(self.Classes),2])

        #Treeview widget making
        Tree = ttk.Treeview(root)
        Tree.grid(column = 0, row = 0)

        Headings = ('first count','second count')
        Tree['column'] = Headings

        Tree.column("#0", width=100, minwidth=100)
        Tree.heading("#0",text="Class")

        for i in range(len(Headings)) :
            Tree.column(Headings[i])
            Tree.heading(Headings[i], text = Headings[i])

        #Insert all classes and their counts
        Empty = []
        Total = []
        Total = list(Total)
        for Idx, Class in enumerate(self.Classes) :
            Values = []
            if Idx == len(self.Classes)-1 :
                for Number in self.Experiment_Count[Idx,:] :
                    Values.append(str(Number))
                    Empty.append('-')
                    Total.append(0)
            else :
                for Number in self.Experiment_Count[Idx,:] :
                    Values.append(str(Number))
            Values = tuple(Values)

            if Class == self.Single_Kinetic_Menu_Var[0].get() :
                Tree.insert("", Idx, text = Class, values=Values, tags = ('BLUE'))
                Tree.tag_configure('BLUE', foreground = 'blue')
            elif Class == self.Single_Kinetic_Menu_Var[1].get() :
                Tree.insert("", Idx, text = Class, values=Values, tags = ('RED'))
                Tree.tag_configure('RED', foreground = 'red')
            elif Class == self.Single_Kinetic_Menu_Var[2].get() :
                Tree.insert("", Idx, text = Class, values=Values, tags = ('GREEN'))
                Tree.tag_configure('GREEN', foreground = 'green')
            elif Class == self.Single_Kinetic_Menu_Var[3].get() :
                Tree.insert("", Idx, text = Class, values=Values, tags = ('CYAN'))
                Tree.tag_configure('CYAN', foreground = 'cyan')
            else :
                Tree.insert("", Idx, text = Class, values=Values)
        Tree.insert('', len(self.Classes), text = '-', values = tuple(Empty))
        Total = np.sum(self.Experiment_Count[:,:], axis = 0)
        Tree.insert('',len(self.Classes)+1, text = 'TOTAL', values = tuple(Total),
                    tags = ('BOLD'))
        Tree.tag_configure('BOLD', font = ('Calibri', 12, 'bold'))


def main():
    Master = tk.Tk()
    Master.title("interface")


    Testy(Master) 

    Master.mainloop()


if __name__ == '__main__' :
    main()

正如您在 运行 代码中看到的那样,我希望分子 1、3、4 和 5 的文本分别为蓝色、红色、绿色和青色。但是,我只能看到黑色的。

-您在 cmd

中使用的 python 是什么版本 (python -V)

-python 的最后一个版本 (3.7) 似乎有颜色标签的错误

-如果您使用的是 python (3.7),只需安装 python 3.6(它也可能适用于较新的版本)

如前所述,这是 tkinter 库 > 8.6.8 的一个已知问题。此版本的 tkinter 预装了较新版本的 Python (> 3.7)。

此处提出了解决此问题的方法: https://core.tcl-lang.org/tk/tktview?name=509cafafae

定义过滤参数的函数

def fixed_map(option):
    # Returns the style map for 'option' with any styles starting with
    # ("!disabled", "!selected", ...) filtered out

    # style.map() returns an empty list for missing options, so this should
    # be future-safe
    return [elm for elm in style.map("Treeview", query_opt=option)
            if elm[:2] != ("!disabled", "!selected")]

使用新函数映射样式

style = ttk.Style()
style.map("Treeview", 
          foreground=fixed_map("foreground"),
          background=fixed_map("background"))

有了这个 tag_configure() 应该可以正常工作。

开始时试试这个

style = ttk.Style()
aktualTheme = style.theme_use()
style.theme_create("dummy", parent=aktualTheme)
style.theme_use("dummy")

示例,使用线程和按钮更新 treeView...使用旋转框更新第 n 行......

from tkinter import *
from tkinter import ttk,messagebox
import time
import threading

def thd():
    time.sleep(4)
    pos = int(xs.get())
    stg= "Row"
    pf = "updated"
    tv.item(pos, text='', values=(stg,pf),  tags = ('fail',))
    
def helloCallBack():
    thd()

ws = Tk()
ws.title('Vik')
ws.geometry('400x300')
ws['bg']='#fb0'

style = ttk.Style()
aktualTheme = style.theme_use()
style.theme_create("dummy", parent=aktualTheme)
style.theme_use("dummy")

tv = ttk.Treeview(ws)
tv['columns']=('Stage', 'Status', )
tv.column('#0', width=0, stretch=NO)
tv.column('Stage', anchor=CENTER, width=80)
tv.column('Status', anchor=CENTER, width=80)
# tv.column('Badge', anchor=CENTER, width=80)
tv.heading('#0', text='', anchor=CENTER)
tv.heading('Stage', text='Id', anchor=CENTER)
tv.heading('Status', text='rank', anchor=CENTER)
# tv.heading('Badge', text='Badge', anchor=CENTER)

tv.insert(parent='', index=0, iid=0, text='', values=('1','1'), tags = 'pass')
tv.insert(parent='', index=1, iid=1, text='', values=('2','2'), tags = 'pass')
tv.insert(parent='', index=2, iid=2, text='', values=('3','3'), tags = 'pass')
tv.insert(parent='', index=3, iid=3, text='', values=('4','4'), tags = 'pass')
tv.insert(parent='', index=4, iid=4, text='', values=('5','5'), tags = 'pass')
tv.tag_configure('fail', foreground='red', background='white', font=('Calibri', 11))
tv.tag_configure('pass', foreground='green', background='white',font=('Calibri', 9))

tv.pack()
xs = Spinbox(ws, from_=0, to=4)
xs.pack()
global posi 
posi = int(xs.get())
ins_button = ttk.Button(
    ws,
    text='Insert',
    command=helloCallBack
)

ins_button.pack(
    ipadx=3,
    ipady=3,
    expand=True
)

exit_button = ttk.Button(
    ws,
    text='Exit',
    command=lambda: ws.quit()
)

exit_button.pack(
    ipadx=3,
    ipady=3,
    expand=True
)

th = threading.Thread(target=thd)
th.start()
ws.mainloop()