Geldbeträge in Entry erfassen

Fragen zu Tkinter.
Antworten
guenther52
User
Beiträge: 5
Registriert: Sonntag 20. Juni 2021, 18:02

Bin schon seit längerer Zeit auf der Suche nach einer Möglichkeit, das Format in einem Entry-Feld zu beeinflussen. Und zwar so, dass man nur Ziffern und ein Komma (oder Punkt) eingeben kann und die Nachkommastellen auf 2 begrenzt sind. Habe schon viel versucht (mit validate z.B.) - funktioniert aber alles nicht so richtig.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Was heißt "nicht so richtig"? Was hast Du probiert? Zeig Deinen den Code Deines Versuchs.
guenther52
User
Beiträge: 5
Registriert: Sonntag 20. Juni 2021, 18:02

Hier einer meiner Versuche - Code teilweise im Internet gefunden. Ich glaube, hiermit ist es schon fast ok. Wenn ich den Betrag in eine Datei speichern würde, müsste ich evtl. das Format anpassen? (z.B. aus der Eingabe "1,2" müsste dann "001,20" werden.

from tkinter import *
from tkinter import ttk

root=Tk()

import re
meldungs_text = StringVar()

def betrag_pruefen(newval, op):
meldungs_text.set('')
# valid = re.match('^[0-9]{3}(\,[0-9]{2})?$', newval) is not None
valid = re.match('^[0-9]+([,][0-9]{2})?$', newval) is not None
button1.state(['!disabled'] if valid else ['disabled'])
if op=='key':
ok_so_far = re.match('^[0-9\,]*$', newval) is not None and len(newval) <= 6
# ok_so_far = re.match('^[0-9][,]*$', newval) is not None and len(newval) <= 6
if not ok_so_far:
meldungs_text.set("nur Ziffern und Komma")
return ok_so_far
elif op=='focusout':
if not valid:
meldungs_text.set("nur Ziffern und Komma")
return valid

betrag_pruefen_wrapper = (root.register(betrag_pruefen), '%P', '%V')

betrag = StringVar()

frame1 = ttk.Frame(root)
frame1.grid(column=0, row=0)
ttk.Label(frame1, text='Betrag:').grid(column=0, row=1, padx=5, pady=5)
e_betrag = ttk.Entry(frame1, textvariable=betrag, validate='all', validatecommand=betrag_pruefen_wrapper)
e_betrag.grid(column=1, row=1, padx=5, pady=5)
button1 = ttk.Button(frame1, text="weiter")
button1.grid(column=2, row=1, padx=5, pady=5)
button1.state(['disabled'])
lb_meldung = ttk.Label(frame1, foreground='red', textvariable=meldungs_text)
lb_meldung.grid(column=1, row=2, padx=5, pady=5, sticky='w')

root.mainloop()
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Alle Importe stehen ganz oben. Benutze keine *-Importe, weil damit verschleiert wird, woher welcher Name kommt.
Alles was eine Funktion braucht, muß sie auch über ihre Argumente bekommen. Benutze keine globalen Variablen.

Warum gibt es einen frame1 und einen button1, wo es doch insgesamt nicht mehr als einen gibt? Variablennamen müssen aussagekräftig sein, irgendwelche Nummern an Namen sind das nicht.
Wenn Du euro_betrag meinst, dann schreib das auch, und nicht e_betrag.

Code: Alles auswählen

import re
import tkinter as tk
from tkinter import ttk
from functools import partial

def betrag_pruefen(weiter_button, meldungs_text, newval, op):
    valid = re.match('^[0-9]+([,][0-9]{2})?$', newval) is not None
    weiter_button.state(['!disabled' if valid else 'disabled'])
    if op=='key':
        valid = re.match('^[0-9\,]*$', newval) is not None and len(newval) <= 6
    if not valid:
        meldungs_text.set("nur Ziffern und Komma")
    else:
        meldungs_text.set('')
    return valid


def main():
    root = tk.Tk()
    meldungstext = tk.StringVar(root)
    betrag = tk.StringVar(root)

    frame = ttk.Frame(root)
    frame.grid(column=0, row=0)
    weiter_button = ttk.Button(frame, text="weiter", state="disabled")
    weiter_button.grid(column=2, row=1, padx=5, pady=5)

    ttk.Label(frame, text='Betrag:').grid(column=0, row=1, padx=5, pady=5)
    betrag_pruefen_wrapper = (root.register(partial(betrag_pruefen, weiter_button, meldungstext)), '%P', '%V')
    euro_betrag = ttk.Entry(frame, textvariable=betrag, validate='all', validatecommand=betrag_pruefen_wrapper)
    euro_betrag.grid(column=1, row=1, padx=5, pady=5)
    ttk.Label(frame, foreground='red', textvariable=meldungstext).grid(column=1, row=2, padx=5, pady=5, sticky='w')
    root.mainloop()

if __name__ == "__main__":
    main()
Und welches konkrete Problem hast Du jetzt? Die Validierung scheint doch zu funktionieren.
guenther52
User
Beiträge: 5
Registriert: Sonntag 20. Juni 2021, 18:02

Hallo Sirius3, danke für die tollen Hinweise. Bin noch ziemlicher Neuling und diese Angaben haben mir sehr geholfen, python besser zu verstehen. Ich versuche immer wieder Beispiele im Internet zu finden. Dabei findet man oft die *-importe. Da ich noch nicht so firm bin, habe ich diese einfach immer übernommen. Das mit den Ziffern an den Variablennamen stammt aus meiner Programmiervergangenheit als Cobol-Programmierer, da war das ziemlich geläufig.
"Partial" kannte ich bisher noch nicht und werde ich mir genauer ansehen.
Nun zu meinen (kleinen) Problemen: wenn ich z.B. einen Wert ohne das Kommazeichen eingebe, sollte das nicht erlaubt sein. Evtl. könnte ich dann einbauen, dass dann beim Speichern der Zahl ein Komma angehängt wird, mit 2 Nullen. Aber ansonsten bin ich eigentlich doch schon zufrieden mit dieser Lösung.
Antworten