Projekt Taschenrechner
Die Button
Schauen wir uns nochmal Zeile 16 aus dem letzten Code-Stand vor der Einführung der PySimpleGUI
an (am Ende von Kapitel 4.3.1.):
ergebnis = eval(zeichenkette)
Wir müssen also dafür sorgen, dass wir alle Zeichen hintereinander in einer Zeichenkette speichern. Das gibt uns dann die Möglichkeit, die "eval()"
-Funktion aufzurufen, wenn wir auf den "="-Button klicken.
Also sorgen wir zuerst dafür, dass wir eine Zeichenkette implementieren, die immer dann gefüllt wird, wenn auf irgendeinen Button außer den 3 Funktionsbutton "C", "=" oder "<-" geklickt wird. Der Code dafür ist denkbar einfach:
...
# Programmschleife
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
if event in '1234567890()+-*/.':
zeichenkette = values['eingabe']
zeichenkette += event
window['eingabe'].update(zeichenkette)
Wir hängen in der Programmschleife also eine weitere if
-Bedingung dran. Dieser Teil wird immer dann durchlaufen, wenn das event
eines der in der in
-Abfrage enthaltenen Zeichen ist. Wenn der Button "8" gedrückt wird, wird auch der Wert "8" übergeben.
Der String "zeichenkette"
wird also in Zeile 24 aus dem Eingabefeld gelesen. Wenn sie noch leer ist, steht halt nichts drin. In Zeile 25 wird der Wert des gedrückten Button an den leeren oder bereits gefüllten String "zeichenkette"
angehängt.
In Zeile 26 wird das Feld "eingabe"
mit dem neuen String aktualisiert. Fertig.
Jetzt kommt die Behandlung der anderen Button.
Kümmern wir uns zuerst um das "C". Das ist nun wirklich einfach, wenn das "C" gedrückt wird, müssen wir nur die Zeichenkette löschen oder leeren, dazu erweitern wir wieder die Programmschleife:
...
# Programmschleife
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
if event in '1234567890()+-*/.':
zeichenkette = values['eingabe']
zeichenkette += event
window['eingabe'].update(zeichenkette)
if event == 'C':
zeichenkette = ''
window['eingabe'].update(zeichenkette)
Nichts überraschendes, oder?
Wenden wir uns nun dem "<-"-Button zu. Was wollen wir erreichen? Das letzte eingegebene Zeichen (also der value des zuletzt geklickten Button) soll gelöscht werden. Hier müssen wir uns eines Tricks bedienen:
...
# Programmschleife
while True:
...
if event == 'C':
zeichenkette = ''
window['eingabe'].update(zeichenkette)
if event == '<-':
laenge = len(zeichenkette)
zeichenkette = zeichenkette[:laenge-1]
window['eingabe'].update(zeichenkette)
Wir lassen uns die Länge der Zeichenkette mittels Funktion "len()"
errechnen und speichern diese in der neuen Variable "laenge" (Zeile 31).
In Zeile 32 übernehmen wir in "zeichenkette"
nur die ersten Stellen ohne die letzte Stelle ("lange-1"
). Haben wir also zum Beispiel (12+3)*21
eingegeben, ist der Wert von "laenge" "9". Nach dem Klick auf den "<-"-Button wird "zeichenkette"
bis zur Stelle "8" gefüllt, es bleibt also der Wert "(12+3)*2"
bestehen.
In Zeile 33 wird die Eingabe mit dem neuen Wert dann überschrieben.
Damit kommen wir zum "="-Button. Die einfachste Umsetzung wäre:
...
# Programmschleife
while True:
...
if event == '=':
ergebnis = eval(zeichenkette)
window['eingabe'].update(ergebnis)
ABER:
Wenn Ihr das umgesetzt habt, gebt mal bitte einen "nicht rechenbaren" String wie "(12+3/*21"
ein. Was passiert?
Richtig, das Programm geht kaputt mit der Fehlermeldung:
Was ist also zu tun? Wir erweitern die "if"
-Anweisung um einen "try/except"
-Block:
…
# Programmschleife
while True:
…
if event == '=':
try:
ergebnis = eval(zeichenkette)
window['eingabe'].update(ergebnis)
except:
print(zeichenkette)
window['eingabe'].update('Error')
Wenn wir das jetzt laufen lassen, sehen wir die nicht verarbeitbare Zeichenkette in der Kommandozeile, in der "eingabe"
wird der String ""
angezeigt, das Programm stürzt aber nicht ab:
Damit sind wir jetzt schon ganz gut aufgestellt. Bis hierhin ist soweit alles klar?
Sehr schön. Damit kommen wir von meiner Seite zur letzten Aufgabe am Taschenrechner. Wir haben bis jetzt alle Button bearbeitet, was der Taschenrechner aber noch nicht kann, ist eine Eingabe über die Tatstatur korrekt zu verarbeiten.
Was passiert bei der Eingabe von "12+3"
über die Tastatur, wenn wir dann den "="-Button drücken? Es kommt zu einer Fehlermeldung:
Den Fehler können wir beheben, indem wir die Variable "zeichenkette"
außerhalb der Schleife definieren:
Besser, aber dann kommt immer noch der String "Error"
:
Aber warum ist das so? Wo liegt der Fehler? Wir haben dem Programm nicht mitgeteilt, dass es auch auf die Eingabe der Tastatur reagieren soll. Das müssen wir noch nachholen. o
Dazu müssen wir an der Instanziierung des Fensters 2 Änderungen vornehmen. Ich habe jetzt mal den finalen Code vollständig aufgelistet:
import PySimpleGUI as sg
# die Elemente im Fenster
layout = [[sg.Input(size=(17, 1), justification='right', key='eingabe',
font=('OCR A Extended', 16))],
[sg.Button('+'), sg.Button('-'), sg.Button('*'), sg.Button('/')],
[sg.Button('7'), sg.Button('8'), sg.Button('9'), sg.Button('<-')],
[sg.Button('4'), sg.Button('5'), sg.Button('6'), sg.Button('(')],
[sg.Button('1'), sg.Button('2'), sg.Button('3'), sg.Button(')')],
[sg.Button('C', button_color=("black","orange")), sg.Button('0'),
sg.Button('.'), sg.Button('=', button_color=("black","orange"))]
]
# das Fenster selber wird erzeugt
window = sg.Window('Taschenrechner', layout, default_button_element_size=(5,2),
auto_size_buttons=False, finalize=True)
window['eingabe'].bind("", "auf_die_Eingabe_gehauen")
zeichenkette = ''
# Programmschleife
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
if event in '1234567890()+-*/.':
zeichenkette = values['eingabe']
zeichenkette += event
window['eingabe'].update(zeichenkette)
if event == 'C':
zeichenkette = ''
window['eingabe'].update(zeichenkette)
if event == '<-':
laenge = len(zeichenkette)
zeichenkette = zeichenkette[:laenge-1]
window['eingabe'].update(zeichenkette)
if event == '=' or event == "eingabe" + "auf_die_Eingabe_gehauen":
if event == "eingabe" + "auf_die_Eingabe_gehauen":
zeichenkette = values['eingabe']
window['eingabe'].update(zeichenkette)
try:
ergebnis = eval(zeichenkette)
window['eingabe'].update(ergebnis)
except:
print(zeichenkette)
window['eingabe'].update('Error')
Damit der Taschenrechner für die Eingabe bereit ist, können wir das Fenster aktivieren, das machen wir mit der Erweiterung "finalize=True"
in Zeile 15. In Zeile 16 "binden" wir "
an das Fenster, sodass wir eine Eingabe verarbeiten können, die mit Enter bestätigt wurde.
Zeile 36 erweitern wir um die "event"
-Abfrage auf die Eingabe mit Enter und wenn die Eingabe über die Tatstatur erfolgt ist, lesen wir zuerst den aktuellen Wert von "eingabe"
und füllen damit "zeichenkette"
.
Damit ist die Eingabe von "12+3"
über die Tastatur mit abschließender Enter-Taste erfolgreich:
Sieht bei Euch auch so aus? Dann von mir ein donnerndes "Bravo!", das habt Ihr sehr gut gemacht, von meiner Seite war es das mit dem Coden.
Inhaltsverzeichnis:
1. Vorwort2. Das Projekt
3. Vorarbeiten
4. Projekt Snake
4.1. Der Funktionsumfang
4.2. Die Planung der Umsetzung
4.3. Das Coden
4.3.1. Datentypen in Python
4.3.2. Eingabe von Zahlen
4.3.3. Rechnen mit der Funktion
eval()
4.3.4. Das Fenster mit
PySimpleGui
4.3.5. Die Button
5. Abschluss