Tkinter - entry eingabe in Liste und csv ausgeben

Fragen zu Tkinter.
Antworten
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

Hallo zusammen,

ich möchte heute meinen ersten Beitrag erstellen, da ich zwar Mega viele Infos aus dem Forum bekommen habe, aber ich einfach zu blöd bin, daraus das zu programmieren, was ich benötige. Ich muss dazu sagen, ich bin blutiger Anfänger und lese mich langsam erst ein.

Mein Wunsch an das von mir erstellte Programm ist:
- Erstellen eines Eingabefensters, wo Attribute einer "Restplatte" eingegeben werden. Plattenname, Länge, Breite, Lagerort etc.
- Übergabe der Werte in eine Liste
- Übergabe der Liste in eine .csv Datei

Bis zum fertigen Eingabefenster konnte ich den Code zusammenschreiben (abgeschrieben, nicht copy ad paste :D )

Ich würde mich über einen Ansatz freuen, wie ich weiter vorgehen muss, damit ich selber den Code erstellen und es dann auch hoffentlich verstehen kann. Ich habe noch weitere Ideen, wie sich das ganze besser noch umfangreiche für uns einsetzten lässt, aber das kommt erst später. :wink:

Anbei den bisherigen Code:

Code: Alles auswählen

import csv
import tkinter as tk
from functools import partial


FIELDS = ['Plattenname', 'Lagerort', 'Länge X', 'Breite Y', 'Dicke', 'Material', 'Stückzahl' ]


def eingabe(entries):
    print(entries)
    for field, text in entries:
        print('%s: "%s"' % (field, text.get()))
        

def makeform_grid(fenster, fields):
    entries=[]
    for i, field in enumerate(fields):
        row, column = divmod(i, 2)
        tk.Label(fenster, text=field).grid(row=row, column=column*2)
        entry = tk.Entry(fenster)
        entry.grid(row=row, column=column*2+1)
        entries.append((field, entry))
    return entries

def main():
    fenster = tk.Tk()
    entries = makeform_grid(fenster, FIELDS)
    tk.Button(fenster, text="Quit", command=fenster.destroy).grid(row=12, column=0, pady=20)
    tk.Button(fenster, text="Erfassen", command=partial(eingabe, entries)).grid(row=12, column=1, padx=20)
    fenster.mainloop()
    
if __name__ == '__main__':
    main()
    
Vielen Dank schon mal an jeden, der sich überhaupt die Mühe macht, das zu lesen.

Viele Grüße
Florian
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Da Du die Werte per `print` ausgeben kannst, kannst Du sie auch in eine Liste packen. Vielleicht möchtest Du auch ein Wörterbuch, damit Du dieses dann per csv.DictWriter inklusive Header in Deine csv-Datei schreiben kannst:

Code: Alles auswählen

def eingabe(entries):
    values = {field: entry.get() for field, entry in entries}
    ...
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

Super Sache, mit dem Wörterbuch. Vielen, vielen Dank, ich bin ein ganzes Stück weitergekommen. (Für meine Verhältnisse. :D)

Ich werde jetzt versuchen, es passend in eine csv zu bekommen und einen weiteren Button einfügen.
Der Button soll die Funktion haben, die Eingabefelder zu leeren um eine weitere Platte ins Wörterbuch einzufügen.
Bei weiteren Fragen, kann ich diesen Beitrag erweitern?

Viele Grüße
Florian
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

Guten Morgen,

leider bin ich nicht sonderlich weit fortgeschritten in meiner Programmierung...
Aktuell ist mein Plan, nach dem drücken des Buttons "Weitere Platte eingeben", das der Inhalt aus den Textfeldern gelöscht wird, um ich eine weitere "Resttafel" in das Wörterbuch einzutragen.

Könnte mir jemand helfen?
Danke.

Code: Alles auswählen

import csv
import tkinter as tk
from tkinter import END
from functools import partial


FIELDS = ['Plattenname', 'Lagerort', 'Länge X', 'Breite Y', 'Dicke', 'Material', 'Stückzahl' ]


def eingabe(entries):
    RESTPLATTE = {field: entry.get() for field, entry in entries}
    print(RESTPLATTE)


def clear(fenster):
    entry=tk.Entry(fenster)
    entry.delete("1.0", "end")


def makeform_grid(fenster, fields):
    entries=[]
    for i, field in enumerate(fields):
        row, column = divmod(i, 2)
        tk.Label(fenster, text=field).grid(row=row, column=column*2)
        entry = tk.Entry(fenster)
        entry.grid(row=row, column=column*2+1)
        entries.append((field, entry))
    return entries

def main():
    fenster = tk.Tk()
    fenster.geometry("480x180")
    fenster.title("Restmaterial eintragen")
    entries = makeform_grid(fenster, FIELDS)
    tk.Button(fenster, text="Quit", command=fenster.destroy).grid(row=12, column=2, padx=20, pady=20)
    tk.Button(fenster, text="Erfassen", command=partial(eingabe, entries)).grid(row=12, column=0, padx=20)

    tk.Button(fenster, text="Weitere Platte eingeben", command=clear).grid(row=12, column=1, padx=20)
    
    fenster.mainloop()
    
if __name__ == '__main__':
    main()
    
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Es macht doch wenig Sinn, in `clear` ein neues tk.Entry zu erzeugen. In `eingabe` greifst Du doch schon auf die vorhandenen Entries zu, zum Inhalt Löschen geht das genauso.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Kannst du nicht einfach Microsoft Access fuer dein Problem benutzen? Damit kann man einfache Eingabemasken fuer tabellarische Daten machen. Und das mit 'klicki-bunti", wie man so schoen sagt.
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

__deets__ hat geschrieben: Dienstag 13. Juli 2021, 11:38 Kannst du nicht einfach Microsoft Access fuer dein Problem benutzen? Damit kann man einfache Eingabemasken fuer tabellarische Daten machen. Und das mit 'klicki-bunti", wie man so schoen sagt.
Das lässt sich sicher mit Access umsetzten und würde auch hier funktionieren.
Aber ich möchte Python programmieren lernen und auch die weitere Verarbeitung der Daten möchte ich mit Python realisieren.
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

Sirius3 hat geschrieben: Dienstag 13. Juli 2021, 11:33 Es macht doch wenig Sinn, in `clear` ein neues tk.Entry zu erzeugen. In `eingabe` greifst Du doch schon auf die vorhandenen Entries zu, zum Inhalt Löschen geht das genauso.
Guten Morgen.

Erstmal vielen Dank für die Antworten, aber ich muss nochmal fragen...

Wie genau muss die Funktion definiert werden? Ich komme einfach nicht weiter.

Danke.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Woher hast du denn die Funktion eingabe? Kannst du erklären, was die tut? Und warum kannst du das nicht in clear machen?
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

Die Funktion hat mir Sirius3 netterweise zur Verfügung gestellt. :D

Ich glaube sie halbwegs verstanden zu haben.

def eingabe(entries):

def = Funktion definieren
eingabe = Name der Funktion
(entries) = Liste mit den Eingabewerten?

RESTPLATTE = {field: entry.get() for field, entry in entries}

RESTPLATTE = das Wörterbuch mit den "Headern"
field = ? Parameter für die Bennenung der Eingabefelder ?
entry.get() = Übernahme der eingegebenen Werte in field?
for field, entry in entries = werden hier die einzelnen entrys den Headern zugeordnet?

print(RESTPLATTE)

Beim Print Befehl bin ich mir relativ sicher, den verstanden zu haben. ;)


Ich habe versucht es in 'clear' genauso zu machen... ohne Erfolg...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das was da in den geschweiften Klammern steht nennt sich "dictionary comprehension", das kannst du mal nachlesen.

Und entries ist eine Liste von Tupeln, aus Name und Entry-Widget. Sieht man hier:

Code: Alles auswählen

        entries.append((field, entry))
Und jetzt die entscheidende Frage: warum kann eingabe auf entries zugreifen, und clear nicht?
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

Weil dem "möchtegern" Programmierer das Verständnis dazu fehlt... (noch ;))
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also ich bin da ein bisschen baff. Wenn du nicht den Drive entwickelst, dich mal zu fragen, warum etwas an einer Stelle geht, und an der anderen nicht, und was da der Unterschied sein koennte - dann wird das einfach nix mit dem Wechsel von Moechtegern zu Kanndas.

Es ist ja voellig ok, Dinge nicht zu verstehen, dann kann man ja fragen, warum etwas wie genau funktionert. Aber so weit kommt es ja noch nicht mal. Du erhoffst dir einfach den naechsten hergeschenkten Code, und dann geht sie weiter, die wilde Fahrt ins Ungewisse, mit fest geschlossenen Augen...

Ich habe dir aus gutem Grund Access vorgeschlagen. Das ist einfacher fuer deinen angepeilten Zweck, und du wirst dir dein Programm hier nicht stueckweise erbetteln koennen - dazu ist das einfach zu viel.

Hier die Loesung, und ich kann nur raten: studier die Unterschiede, und versuch sie zu verstehen. Dokumentation lesen und eigene Experimente machen inklusive. Es wird sonst nix, kannst du mir glauben.

Code: Alles auswählen

import csv
import tkinter as tk
from tkinter import END
from functools import partial


FIELDS = ['Plattenname', 'Lagerort', 'Länge X', 'Breite Y', 'Dicke', 'Material', 'Stückzahl' ]


def eingabe(entries):
    RESTPLATTE = {field: entry.get() for field, entry in entries}
    print(RESTPLATTE)


def clear(entries):
    for _name, entry in entries:
        entry.delete(0, "end")


def makeform_grid(fenster, fields):
    entries=[]
    for i, field in enumerate(fields):
        row, column = divmod(i, 2)
        tk.Label(fenster, text=field).grid(row=row, column=column*2)
        entry = tk.Entry(fenster)
        entry.grid(row=row, column=column*2+1)
        entries.append((field, entry))
    return entries

def main():
    fenster = tk.Tk()
    fenster.geometry("480x180")
    fenster.title("Restmaterial eintragen")
    entries = makeform_grid(fenster, FIELDS)
    tk.Button(fenster, text="Quit", command=fenster.destroy).grid(row=12, column=2, padx=20, pady=20)
    tk.Button(fenster, text="Erfassen", command=partial(eingabe, entries)).grid(row=12, column=0, padx=20)

    tk.Button(fenster, text="Weitere Platte eingeben", command=partial(clear, entries)).grid(row=12, column=1, padx=20)

    fenster.mainloop()

if __name__ == '__main__':
    main()
Caspar311
User
Beiträge: 8
Registriert: Dienstag 22. Oktober 2019, 05:25

__deets__ hat geschrieben: Mittwoch 14. Juli 2021, 09:37 Also ich bin da ein bisschen baff. Wenn du nicht den Drive entwickelst, dich mal zu fragen, warum etwas an einer Stelle geht, und an der anderen nicht, und was da der Unterschied sein koennte - dann wird das einfach nix mit dem Wechsel von Moechtegern zu Kanndas.
Ich danke Dir wirklich für die Hilfestellung und freue mich darüber weiter den Code zu testen und weiterentwickeln.

Es ist das erste Programm, dass ich hier veröffentlicht habe und meine Motivation war sehr groß. Ich gebe zu ich habe mich dann dem einfachen Weg hingegeben und wollte eine schnelle Lösung.

Fürs weitere programmieren, werde ich Deinen Rat befolgen.
Antworten