Format a single cell / element, not an entire row in tkinter ttk treeview

I am currently using a function to display a pandas frame in a spreadsheet format format. I would like to be able to add some functions to format individual cells of the tree structure based on their contents, for example. if they contain the substring "X" or if their value is greater than Y.

Currently implemented update function:

def updateTree(self, dataframe): ''' Updates the treeview with the data in the dataframe parameter ''' #Remove any nan values which may have appeared in the dataframe parameter df = dataframe.replace(np.nan,'', regex=True) #Currently displayed data self.treesubsetdata = dataframe #Remove existing items for item in self.tree.get_children(): self.tree.delete(item) #Recreate from scratch the columns based on the passed dataframe self.tree.config(columns= []) self.tree.config(columns= list(dataframe.columns)) #Ensure all columns are considered strings and write column headers for col in dataframe.columns: self.tree.heading(col,text=str(col)) #Get number of rows and columns in the imported script self.rows,self.cols = dataframe.shape #Populate data in the treeview for row in dataframe.itertuples(): self.tree.insert('', 'end',values = tuple(row[1:])) #Minimise first column self.tree.column('#0',width=0) self.tree.update() 

Can someone confirm that you really can edit a single cell in view mode?

If so, are there any ideas as to how this can be implemented?

+7
python tkinter ttk treeview
source share
2 answers

Unable to set the style of individual cells in Treeview; only whole lines can use the tag attribute.

If you need a table of values, I would recommend using only ttk.Label widgets, which you can format in a huge number of ways. For example:

 import Tkinter as tk import ttk import pandas as pd from random import randrange PADDING = dict(padx=3, pady=3) class GridView(tk.Frame): def __init__(self, master=None, **kwargs): tk.Frame.__init__(self, master, **kwargs) self.labels = [] style = ttk.Style() style.configure("red.TLabel", background='red') style.configure("green.TLabel", background='green') style.configure("header.TLabel", font = '-weight bold') def set(self, df): self.clear() for col, name in enumerate(df.columns): lbl = ttk.Label(self, text=name, style='header.TLabel') lbl.grid(row=0, column=col, **PADDING) self.labels.append(lbl) for row, values in enumerate(df.itertuples(), 1): for col, value in enumerate(values[1:]): lbl = ttk.Label(self, text=value, style=self.get_style(value)) lbl.grid(row=row, column=col, **PADDING) self.labels.append(lbl) @staticmethod def get_style(value): if value > 70: return "red.TLabel" elif value < 30: return "green.TLabel" else: return None def clear(self): for lbl in self.labels: lbl.grid_forget() self.labels = [] class GUI(tk.Frame): def __init__(self, master=None, **kwargs): tk.Frame.__init__(self, master, **kwargs) self.table = GridView(self) self.table.pack() btn = ttk.Button(self, text="populate", command=self.populate) btn.pack() btn = ttk.Button(self, text="clear", command=self.table.clear) btn.pack() def populate(self): self.table.set(new_rand_df()) def main(): root = tk.Tk() win = GUI(root) win.pack() root.mainloop() def new_rand_df(): width = 5 height = 5 return pd.DataFrame([[randrange(100) for _ in range(width)] for _ in range(height)], columns = list('abcdefghijklmnopqrstuvwxyz'[:width])) if __name__ == '__main__': main() 
+1
source share

this is possible using custom cellrenderer in Gtk3, for example:

 import gi gi.require_version( 'Gtk', '3.0' ) from gi.repository import Gtk, GObject class My_CellRendererText( Gtk.CellRendererText ): def __init__( self ): super().__init__() def do_render( self, cr, widget, background_area, cell_area, flags ): cell_text = self.props.text self.props.underline = ( "X" in cell_text ) self.props.weight = 700 if ( cell_text.isdigit() and int( cell_text ) > 3 ) else 400 return Gtk.CellRendererText.do_render( self, cr, widget, background_area, cell_area, flags ) GObject.type_register( My_CellRendererText ) 
+1
source share

All Articles