Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python : tkinter treeview colors are not updating

This is my first post, please excuse me if I made mistake in the format, I will gladly change it if required.

I'm creating an interface for scientific datas analysis using Tkinter. For a list of molecules, four can be represented in separate plots. On the side, I use a Treeview to show some numbers about all molecules. (not just the displayed ones) When a treeview row is about a displayed plot, i want that row's text to be the same color.

For each displayed graph, I place a different tag on the row that represents it and then use the tag method to change the foreground color to the plot's color.

The code used to work fine, but now it has stopped working without any changes to the my code. The setting of the foreground color with the tags doesn't change the color. A few lines later, I also use that method to change a row to be bold and it works fine.

I managed to confirm that the lines of code are read correctly : if i set the color to a value that is unrecognized, i get a tkinter error when executing as expected. Furthermore, using some prints, the if/elif are executed as expected at the correct moment (no error in the logic tests).

The code works fine on another computer leading me to believe there is a problem with some python packages. The two computers have the same ttk version (0.3.1) and I updated all my modules after noticing the problem to be sure it is not an outdated package.

The only change that was made to the computer is the removal and re-installation of anaconda and the environment now with the added installation (with pip) of pyinstaller in the used environment (when I installed pyinstaller in the original environment, I had modified other important package by mistake and had to reinstall anaconda from scratch to have it work again)

I have tried creating another identical environment without the pyinstaller module and I get the same result.

I have lost count of how many times I have uninstalled and reinstalled anaconda to fix problems. If possible, I would really like not to have to reinstall it all over again.

I have isolated the piece of the interface's code that makes the treeview object. After testing, the snip of code bellow gives me the same issue.

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()

As you might see by running the code, I expect the text of molecules 1, 3, 4 and 5 to be colored blue, red, green and cyan respectively. However, I can only see them in black.

like image 830
Gonzalez87 Avatar asked Dec 18 '22 17:12

Gonzalez87


2 Answers

As already mentioned this is a known issue with the tkinter library > 8.6.8. This version of tkinter is preinstalled with newer versions of Python (> 3.7).

A work around for this has been proposed here: https://core.tcl-lang.org/tk/tktview?name=509cafafae

Define the function that filters out arguments

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")]

Map the styling using the new function

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

With this the tag_configure() should work as intended.

like image 166
GinTonic Avatar answered Jan 08 '23 19:01

GinTonic


-what version of python are you using (python -V) in cmd

-the last version(3.7) of python seems like it has bugs to color tags

-if you are using python (3.7) just install python 3.6 (it may work with newer version also)

like image 24
Ali Avatar answered Jan 08 '23 19:01

Ali