2017-03-08 2 views
7

Ich verwende derzeit eine Funktion, um eine Pandas Dataframe in einem Tabellenformat anzeigen. Ich möchte in der Lage sein, einige Funktionen hinzuzufügen, um einzelne Zellen der Baumansicht basierend auf deren Inhalt zu formatieren, z. wenn sie Zeichenkette enthalten ‚X‘ oder, wenn ihr Wert höher als Y. istFormat einzelne Zelle/Element lieber als ganze Zeile in Tkinter Ttk Baumansicht

Die Update-Funktion zur Zeit implementiert ist wie folgt:

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

jemand bestätigen kann, dass man in der Tat bearbeitet eine einzelne Zelle in einem treview?

Wenn ja, gibt es Ideen, wie dies umgesetzt werden könnte?

+0

Ich glaube nicht, dass das möglich ist. Gibt es einen Grund, warum Sie nicht stattdessen ein einfaches Raster aus Label- oder Entry-Widgets erstellen möchten? – Novel

+0

Ich benutze eine benutzerdefinierte Klasse erstellen, anzeigen, fügen Sie Bildlaufleisten, zu aktualisieren und komplexe Art durchführen und die Filter gebunden Tasten auf die angezeigten Daten. Ich bin mir nicht sicher, ob ich den Rahmen an dieser Stelle überarbeiten kann. Wenn es nicht möglich ist, muss ich die Funktionalität überdenken. – user3535074

Antwort

1

Es ist nicht möglich, den Stil einzelner Zellen in Treeview zu setzen; Nur ganze Zeilen können das Tag-Attribut verwenden.

Wenn Sie nur eine Tabelle von Werten wollen, dann würde ich empfehlen, nur ttk.Label Widgets, die Sie auf eine Vielzahl von Möglichkeiten formatieren können. Zum Beispiel:

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

Es scheint unmöglich zu sein, das zu tun, was ich in der traditionellen ttk.Treeview wollte, daher akzeptiere ich Jonathans Antwort für das Vorschlagen einer alternativen Lösung im Detail. – user3535074

1

dies ist möglich, eine individuelle Zellrenderer in Gtk3 verwenden, z.B .:

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) 
+0

Ist das möglich mit der ttk Treeview? Oder müsste ich die GUI von Grund auf mit Gtk bauen? – user3535074

+0

Ja, dieser CellRenderer benötigt eine Gtk.Treeview. Ich weiß nicht, ob es auch mit ttk funktionieren kann, aber ich denke nicht. –

Verwandte Themen