Falsches Fensterformat, bei Änderung der Spaltenanzahl in Tabelle

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Habe das Beispiel ein wenig modifiziert:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# For Python3.x

import tkinter as tk
import tkinter.ttk as ttk
'''
Created on Mar 21, 2016

@author: Bill Begueradj
'''

class Begueradj(tk.Frame):
    '''
    classdocs
    '''  
    def __init__(self, parent, label, data, width):
        '''
        Constructor
        '''
        tk.Frame.__init__(self, parent)
        self.parent=parent
        self.label=label
        self.data=data
        self.width=width
        self.initialize_user_interface()

    def initialize_user_interface(self):
        """Draw a user interface allowing the user to type
        items and insert them into the treeview
        """
        self.parent.title("Canvas Test")       
        self.parent.grid_rowconfigure(0,weight=1)
        self.parent.grid_columnconfigure(0,weight=1)
        self.parent.config(background="lavender")

        self.tree = ttk.Treeview(self.parent, columns=self.label)
        for i, name in enumerate(self.label):
            name = name.upper()
            text = '{}:'.format(name)
            width = self.width[i] * 10
            # Set the treeview
            self.tree.heading('{}'.format(i), text=name, anchor=tk.W)
            self.tree.column('{}'.format(i), width=width, stretch=tk.YES)
            self.tree.grid(row=0, columnspan=i+1, sticky=tk.NSEW)
            # Define the different GUI widgets
            if name == 'LIEFERANT':
                self.supplier_label = tk.Label(self.parent, width=width,
                    bg='lavender', text = text, anchor=tk.E)
                self.supplier_entry = tk.Entry(self.parent)
                self.supplier_label.grid(row = 1, column = 0, sticky = tk.E)
                self.supplier_entry.grid(row = 1, column = 1, sticky = tk.W)
            elif name == 'ARTIKEL':
                self.article_label = tk.Label(self.parent, width=width,
                    bg='lavender',  text = text, anchor=tk.E)
                self.article_entry = tk.Entry(self.parent)
                self.article_label.grid(row = 2, column = 0, sticky = tk.E)
                self.article_entry.grid(row = 2, column = 1, sticky = tk.W)

        self.submit_button = tk.Button(self.parent, text = "Insert",
            command = self.insert_data)
        self.submit_button.grid(row = 3, column = 1, sticky = tk.W)
        self.exit_button = tk.Button(self.parent, text = "Exit",
            command = self.output_data)
        self.exit_button.grid(row = 3, column = 2, sticky = tk.W)

        self.treeview = self.tree
        # Initialize the counter
        self.i = 1


    def insert_data(self):
        """
        Insertion method.
        """
        data = self.data[(self.supplier_entry.get(), self.article_entry.get())]
        pos = '#{}{}'.format((3 - len(str(self.i))) * '0', self.i)
        data[0] = str(pos)
        self.treeview.insert('', 'end', text='ITEM_{}'.format(self.i),
            values=[x.upper() for x in data])
        # Increment counter
        self.i = self.i + 1  


    def output_data(self):
        """
        Output method.
        """
        self.parent.quit()
        for child in self.treeview.get_children():
            print(self.treeview.item(child)["values"])

def main():
    root=tk.Tk()
    label = ['position', 'lieferant', 'artikel', 'benennung', 'hersteller',
            'herstellernummer', 've', 'inhalt', 'vk', 'mwst']
    data = {
        ('123', '123456789') :['', '123', '123456789',
        'produkt 123456789, din a4, weiß, 80g',
        'hersteller', 'herstellernummer', 'stück', '1', '3.25', '0.19']
        }
    width = [10, 10, 20, 50, 25, 30, 10, 10, 15, 10]
    d=Begueradj(root, label, data, width)
    root.mainloop()

if __name__=="__main__":
    main()
Bei "EXIT" lasse ich mir die Values ausgeben.
Ich habe dabei bemerkt, dass bei reinen Zahlenfeldern, wenn eine "0" voran steht diese entfernt wird.
Es gibt ja z.B. Bestellartikel, bei der eine 0 voran steht > 01236689 == 1236689?
Ist das so gewollt, oder gibt es da einen Trick, dies zu unterbinden?

Auch, ist die erste Spalte sehr breit, wie kann ich da die Breite verändern?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dein Beispiel funktioniert fuer mich nicht, beim versuch, ein Datum einzutragen kracht es, weil data ein Dictionary ist, bei dem du auf einen nicht-existierenden Schuessel zugreifen willst.

Code: Alles auswählen

(foobar) beer:tmp deets$ python /tmp/test.py
2018-12-06 18:20:29.929 Python[75513:738406] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to (null)
Exception in Tkinter callback
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
    return self.func(*args)
  File "/tmp/test.py", line 76, in insert_data
    data = self.data[(self.supplier_entry.get(), self.article_entry.get())]
KeyError: ('peter', 'wagen')
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ja, ich habe hier ein Dictionary verwendet, um mit einem Produkt-Schlüssel, eine Datenzeile zu erstellen, im Gegensatz zur reinen Eingabe.
Als Schlüssel, verwende dies: Lieferant: 123, Artikel: 123456789 (Steht auch im Code unten)
Den KeyError kann man ja abfangen, was ich jetzt in dem Beispiel nicht getan habe.
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@Nobuddy: Doc-Strings für Module müssen vor den Importen stehen. Der Doc-String für die Klasse und __init__ sind nicht wirklich sinnvoll, bzw. falsch. Das was in `initialize_user_interface` steht sollte direkt __init__ stehen. Das Kind sollte nicht den `parent` konfigurieren.
Begueradj ist ein Frame, Du packst aber alles in parent. Die Widgets sollten aber im Frame sein.

supplier_label und article_label werden später nicht mehr gebraucht und sollten keine Attribute sein. Die beiden if-Blöcke sind quasi identisch und können zusammengefaßt werden. submit_button und exit_button werden später nicht mehr gebraucht und sollten keine Attribute sein.
`i` ist ein sehr schlechter Attributname.

Zeile 77ff: Wenn man führende Nullen will, macht man das über format-Parameter, pos ist schon ein String, den nochmal in einen String umzuwandeln ist unsinnig.

Code: Alles auswählen

data[0] = '#{:03d}'.format(self.i)
Warum konvertierst Du alles zu Großbuchstaben?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ich verwende Großbuchstaben in den Datenzeilen, dies vereinheitlicht ich die Texte.
Ich verwende dies z.B. bei Produktdaten. Ausschlaggebend war mit unter die verschiedenen Schreibweisen von Lieferanten.
Z.B. Herstellernummer: cB-123abc, Cb-123-abc, CB123-abc
Nach meiner Formatierung, wird daraus: CB123ABC
Buchstaben und Zahlen bleiben in der Reihenfolge bestehen, der Rest wird entfernt und ist nun untereinander vergleichbar.

Ich habe das Beispiel aus dem Beispiel-Link von weiter oben verwendet und wie gepostet abgeändert.
Das was Du über "Doc-Strings für Module müssen vor den Importen stehen" geschrieben hast, verstehe ich ansatzweise, weis aber nicht wie ich dies hier umsetzen soll, vielleicht kannst Du mir anhand von Code dies verdeutlichen?
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

"Vor" bezieht sich auf "steht in einer Zeile, die eine kleinere Zeilennummer hat":

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# For Python3.x
'''
Created on Mar 21, 2016

@author: Bill Begueradj
'''
import tkinter as tk
import tkinter.ttk as ttk
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ok, stehe aber da noch immer auf dem "Schlauch" ....

Haben die Buttons mit Eingabefelder eine eigene GUI und ich übergebe das Ergebnis an "class Begueradj"?
Wenn nein, vielleicht doch ein kleines Beispiel, damit ich das verstehen kann?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ich glaube, dass ich so langsam dahinter komme.
Ist dies, so wie Du meinst?

Code: Alles auswählen

def main():
    root=tk.Tk()
    label = ['position', 'lieferant', 'artikel', 'benennung', 'hersteller',
            'herstellernummer', 've', 'inhalt', 'vk', 'mwst']
    data = {
        ('123', '123456789') :['', '123', '123456789',
        'produkt 123456789, din a4, weiß, 80g',
        'hersteller', 'herstellernummer', 'stück', '1', '3.25', '0.19']
        }
    width = [10, 10, 20, 50, 25, 30, 10, 10, 15, 10]
    
    d=Begueradj(root, label, data, width)
    # Define the different GUI widgets
    label_0 = tk.Label(root, width=15, bg='lavender', text = 'LABEL0',
        anchor=tk.E)
    value_0 = tk.Entry(root)
    label_0.grid(row = 2, column = 0, sticky = tk.E)
    value_0.grid(row = 2, column = 1, sticky = tk.W)
    label_1 = tk.Label(root, width=15, bg='lavender', text = 'LABEL1',
        anchor=tk.E)
    value_1 = tk.Entry(root)
    label_1.grid(row = 3, column = 0, sticky = tk.E)
    value_1.grid(row = 3, column = 1, sticky = tk.W)
    # Set the buttons
    submit_button = tk.Button(root, text = "Insert", command = d.insert_data)
    submit_button.grid(row = 4, column = 1, sticky = tk.W)
    exit_button = tk.Button(root, text = "Exit", command = d.output_data)
    exit_button.grid(row = 4, column = 2, sticky = tk.W)

    root.mainloop()

if __name__=="__main__":
    main()
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ich denke mal, dass ich damit auf dem richtigen Weg bin.
x- und y_scroll sind auch dabei.

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# For Python3.x

import tkinter as tk
import tkinter.ttk as ttk
'''
Created on Mar 21, 2016

@author: Bill Begueradj
'''

class Begueradj(tk.Frame):
    '''
    classdocs
    '''  
    def __init__(self, parent):
        '''
        Constructor
        '''
        tk.Frame.__init__(self, parent)
        self.parent=parent
        self.initialize_user_interface()

    def initialize_user_interface(self):
        """Draw a user interface allowing the user to type
        items and insert them into the treeview
        """
        self.parent.title("Canvas Test")       
        self.parent.grid_rowconfigure(0, weight=1)
        self.parent.grid_columnconfigure(0, weight=1)
        self.parent.config(background="lavender")

        # Set the treeview
        self.tree = ttk.Treeview(self.parent, selectmode="extended",
            columns=self.parent.label)
        # Set the scrollbar
        xcroll =tk.Scrollbar(self.parent, orient=tk.HORIZONTAL,
            bg='lightblue', activebackground='lightsteelblue',
            troughcolor='white', command=self.tree.xview)
        ycroll =tk.Scrollbar(self.parent, orient=tk.VERTICAL,
            bg='lightblue', activebackground='lightsteelblue',
            troughcolor='white', command=self.tree.yview)
        self.tree.configure(yscrollcommand=ycroll.set,
            xscrollcommand=xcroll.set)
        ycroll.grid(row=0, column=4, sticky=tk.NS, in_=self.parent)
        xcroll.grid(row=1, column=0, columnspan=4, sticky=tk.EW,
            in_=self.parent)
        self.parent.rowconfigure(0, weight=1)
        self.parent.columnconfigure(0, weight=1)
        # Set the binding for three
        self.tree.bind("<Double-Button-1>", self.select_data)
        self.tree.bind('<KP_Enter>', self.select_data)
        self.tree.bind('<Return>', self.select_data)
        self.treeview = self.tree
        # Initialize the counter
        self.i = 1


    def select_data(self, event):
        item = self.treeview.focus()
        selection = self.treeview.item(item)["values"]
        print(selection)
    

def main():
    root=tk.Tk()
    root.label = ['position', 'lieferant', 'artikel', 'benennung', 'hersteller',
            'herstellernummer', 've', 'inhalt', 'vk', 'mwst']
    products = {
        ('123', '123456789') :['', '123', '123456789',
        'produkt 123456789, din a4, weiß, 80g',
        'hersteller', 'herstellernummer', 'stück', '1', '3.25', '0.19']
        }
    width2label = [10, 10, 20, 50, 25, 30, 10, 10, 15, 10]
    
    d=Begueradj(root)
    # Set the label for table and the entry-fields
    for i, name in enumerate(root.label):
        name = name.upper()
        text = '{}:'.format(name)
        width = width2label[i] * 10
        # Set the treeview
        d.tree.heading('{}'.format(i), text=name, anchor=tk.W)
        d.tree.column('{}'.format(i), width=width, stretch=tk.YES)
        d.tree.grid(row=0, columnspan=i+1, sticky=tk.NSEW)
    # Define the different GUI widgets
    root.label_0 = tk.Label(root, width=15, bg='lavender', text = 'LABEL0',
        anchor=tk.E)
    root.value_0 = tk.Entry(root)
    root.label_0.grid(row = 2, column = 0, sticky = tk.E)
    root.value_0.grid(row = 2, column = 1, sticky = tk.W)
    root.label_1 = tk.Label(root, width=15, bg='lavender', text = 'LABEL1',
        anchor=tk.E)
    root.value_1 = tk.Entry(root)
    root.label_1.grid(row = 3, column = 0, sticky = tk.E)
    root.value_1.grid(row = 3, column = 1, sticky = tk.W)
    # Set the buttons
    submit_button = tk.Button(root, text = "Insert",
        command = lambda: insert_data(d, products, root.value_0, root.value_1))
    submit_button.grid(row = 4, column = 1, sticky = tk.W)
    exit_button = tk.Button(root, text = "Exit",
        command = lambda: output_data(d))
    exit_button.grid(row = 4, column = 2, sticky = tk.W)

    root.mainloop() 


def insert_data(d, products, value_0, value_1):
    """
    Insertion method.
    """

    try:
        key = value_0.get(), value_1.get()
        data = products[key]
    except KeyError:
        if set(key) == {''}:
            print('Neuer Datensatz')
        return
    pos = '#{}{}'.format((3 - len(str(d.i))) * '0', d.i)
    data[0] = str(pos)
    d.treeview.insert('', 'end', text='ITEM_{}'.format(d.i),
        values=[x.upper() for x in data])
    # Increment counter
    d.i = d.i + 1  


def output_data(d):
    """
    Output method.
    """

    d.quit()
    for child in d.treeview.get_children():
        print(d.treeview.item(child)["values"])

if __name__=="__main__":
    main()
Antworten