Treeview mit Hiearchy zur Tabellenerzeugung

Fragen zu Tkinter.
Antworten
stefanxfg
User
Beiträge: 85
Registriert: Sonntag 2. April 2017, 14:11

Hallo, ich versuche eine Tabelle zu erzeugen, welche zunächst Hauptzeilen erzeugt, die dann über das Pluszeichen Datenzeilen erzeugen. Die Datenzeilen sind immer den Hauptzeilen zugehörig und es können beliebig viele Datenzeilen zu jeder Hauptzeile zugeordnet sein.

Ich hatte mich entschieden, zunächst über plumpe Entrys mit Button_commands ein Dictionary zu füllen. Das dictionary self.data wird in der Klasse initialisiert. Dann werden die Daten von einer anderen Klassen gesendet und so eingefügt.

Code: Alles auswählen

    def add_main_line(self,name_line):
        
        if not name_line in self.data:
            self.data[name_line] = {}
            self.build_table()
        
    def add_sub_line(self,val_height):
        
        if not val_height in self.data[self.sub_value]:
            self.data[self.sub_value][val_height] = {}
            self.data[self.sub_value][val_height][val_height] = val_height
            self.data[self.sub_value][val_height]['width'] = self.default_setting.get('width')
            self.data[self.sub_value][val_height]['remark'] = self.default_setting.get('remark')
            self.build_table()
Wie gesagt würde ich gern das Ganze über ein Dictionary machen. Das soll dann als Vorlage für die Tabellenerzeugung dienen. Dazu gibt es dann die Methode self.build_table. Die Referenz self.sub_value wird über eine Selction der Treeview-Tabelle gemacht. Die Referenz val_height sind gesendete Daten, welche ich als keys und als value verwende.

Damit wird nun ein Dictionary erzeugt, welches die folgende Form mit Beispielwerte besitzt: {'1':{'2':{'2':'2'},'3':{'3':'3'}}}

Aus meiner Sicht ist die Staffelung notwendig, da die erste Referenz (hier mit 1 bezeichnet) die ID der Hauptzeile bedeutet. Die zweite Referenz bedeutet die ID der Datenzeile und dort sind dann die Values der Treeviewtabelle gespeichert.
Folgendermaßen lasse ich die Tabelle erzeugen.

Code: Alles auswählen

    def rebuild_table(self):
    
        for child in self.container.treeview.get_children():
           self.container.treeview.delete(child)
        count_A = 0
        count_B = 0
        for row,key in enumerate(sorted(self.data.keys(),key=lambda x: int(x))):
            self.iid = self.container.treeview.insert('', count_A, text=(str(key)))
            for rowB,keyB in enumerate(sorted(self.data[key].keys(),key=lambda x: int(x))):
                if self.data[key]:
                    self.container.treeview.insert(self.iid,'end', text=(keyB), values=(self.default_setting.get('width')+" mm", self.default_setting.get('remark'))) 
            count_A += 1
Also die Tabelle wird immer gelöscht und neu aufgebaut. Eben so, wie das Dictionary aufgebaut ist. Mein Problem ist nun beim Löschen von Zeilen. Ich weiß nicht, wie ich beim Selectieren der Zeile, das Dictionary updaten kann. Es wird nur die ID der jeweiligen Zeile ausgegeben. Aber ich benötige die ID der Hauptzeile ebenfalls , damit in der Ansteurung des Dictionary auch in der richtigen Hauptzeile gelöscht werden kann. Kennt sich jemand mit Treeview besser aus?
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@stefanxfg: Welche Art von Daten willst Du eigentlich speichern? Wörterbücher scheinen mir hier die falsche Datenstruktur. Sollen die Werte immer sortiert sein? Reicht es nicht, die Baumstruktur im Treeview selbst zu speichern?
stefanxfg
User
Beiträge: 85
Registriert: Sonntag 2. April 2017, 14:11

Wahrscheinlich hast du recht. Ich sollte vielleicht das Konstrukt genau umkehren. Ich werde die Tabelle füllen und leeren, und daraufhin ein Dictionary verwenden, um anschließend die Daten zu speichern bzw. weiter zu verwenden.
stefanxfg
User
Beiträge: 85
Registriert: Sonntag 2. April 2017, 14:11

NUn ich bin erst einmal so vorgegangen und stoße nun an das Problem, dass die Datenzeilen nummerisch sortiert werden sollen. Ich würde gern beliebig viele Hauptzeilen erzeugen und auch dazu gehörig beliebig viele Datenzeilen. Die Datenzeilen, zugehörig einer Hauptzeile, sollen jeweils sortiert werden. Ist das so mit dem Code richtig. Denn in der GUI wird keine Sortierung angezeigt. Auch die Prints werden nicht gezeigt. Was mache ich falsch?

class TableCode:

def __init__(self, container):
self.container = container

self.container.treeview.heading('#0', text='Spalte 1')
self.container.treeview.heading('#1', text='Spalte 2')
self.container.treeview.heading('#2', text='Spalte 3')

self.container.treeview.column('#0', width=30)
self.container.treeview.column('#1', width=15)
self.container.treeview.column('#2', stretch=tk.YES)


self.default_setting = {
'width' : '0',
'heigth' : '0',
'remark' : 'nothing',
}

# Data dictionary ===================================
self.data = {}
name_line="0"


subscribe_abo(self.container,'TREE_MAIN_LINE_ADD',self.add_main_line)
subscribe_abo(self.container,'TREE_SUB_LINE_ADD',self.add_sub_line)

subscribe_abo(self.container,'TREE_DELETE_ALL_LINES',self.delete_all_data)
subscribe_abo(self.container,'TREE_DELETE_SINGLE_LINES',self.delete_single_elements)

self.container.treeview.bind('<<TreeviewSelect>>', self.select_tree_mainrow)

def add_main_line(self,name_line):


self.iid = self.container.treeview.insert('', 'end', text=(name_line))


def add_sub_line(self,val_height):

self.container.treeview.insert(self.sub_id,'end', text=('Höhe h [mm] = '+val_height), values=(self.default_setting.get('width')+" mm", self.default_setting.get('remark')))


col='#0'
self.container.treeview.heading(col, text=col, command=lambda _col=col: self.treeview_sort_column(self.container.treeview, col, False))
#self.update_dict()


def treeview_sort_column(self,tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(key=lambda t: int(t[0]), reverse=reverse)
print(l)
print('hi')

for index, (val, k) in enumerate(l):
tv.move(k, '', index)

tv.heading(col,command=lambda: self.treeview_sort_column(self,tv, col, not reverse))
stefanxfg
User
Beiträge: 85
Registriert: Sonntag 2. April 2017, 14:11

Ich habe noch einmal darüber nachgedacht. Eigentlich brauche ich nur diesen Code-Anteil. Der kann gleich beim Zeilenanlegen eingefügt werden, um das Sortieren zu bewerkstelligen.

Code: Alles auswählen

    def add_main_line(self,name_line):
        

        self.iid = self.container.treeview.insert('', 'end', text=(name_line))

        l = [(self.container.treeview.set(k, '#0'), k) for k in self.container.treeview.get_children('')]

        l.sort(reverse = descending)

        for index, item in enumerate(l):
            self.container.treeview.move(item[1], '', index)

Aber ich bezweifle, dass man das für die Hauptzeilen und Datenzeilen getrennt machen kann. Ich bezweifle, dass die Datenzeilen zu einer Hauptzeile geordnet werden.

Ich glaube, dass man das mit dem Dictionary besser machen kann. Oder was meinst du Sirius3?
Antworten