Fehlermeldung obwohl es erst funktioniert hat

Fragen zu Tkinter.
Antworten
Benutzeravatar
Gödel
User
Beiträge: 20
Registriert: Samstag 16. April 2022, 15:32

Hi also mein Code hat erst einwandfrei funktioniert und jetzt wo ich ihn wieder geöffnet habe tut er gar nicht mehr und es blobbt ständig diese Fehlermeldung auf:
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3312.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\Finja\PycharmProjects\Calculator\main.py", line 31, in b_equal
e.insert(0, f_num + int(second_number))
ValueError: invalid literal for int() with base 10: ''

Mir fällt nicht ein wie ich das beheben könnte, deshalb meine Frage ob mir irgendjemand dabei helfen kann.

Hier der Code:

Code: Alles auswählen

import math
from math import sqrt
from tkinter import *
root = Tk()
root.title("Calculator")


e = Entry(root, width=35, borderwidth=5)
e.grid(row=0, column=0, columnspan=3, padx=10, pady=10)
#e.insert(0, "")
def b_clear():
    e.delete(0, END)

def b_clicked(number):
    current = e.get()
    e.delete(0, END)
    e.insert(0,str(current) + str(number))

def b_add():
    first_number = e.get()
    global f_num
    global math
    math = "addition"
    f_num = int(first_number)
    e.delete(0, END)
def b_equal():

    e.delete(0, END)
    second_number = e.get()
    if math == "addition":
        e.insert(0, f_num + int(second_number))
    if math == "subtraction":
        e.insert(0, f_num - int(second_number))
    if math == "multiplication":
        e.insert(0, f_num * int(second_number))
    if math == "division":
        e.insert(0, f_num / int(second_number))


def b_sub():
    first_number = e.get()
    global f_num
    global math
    math = "subtraction"
    f_num = int(first_number)
    e.delete(0, END)
def b_mul():
    first_number = e.get()
    global f_num
    global math
    math = "multiplication"
    f_num = int(first_number)
    e.delete(0, END)
def b_div():
    first_number = e.get()
    global f_num
    global math
    math = "division"
    f_num = int(first_number)
    e.delete(0, END)






# Creat oru buttons

b1 = Button(root, text='1', padx=40, pady=20, command=lambda: b_clicked(1))
b2 = Button(root, text='2', padx=40, pady=20, command=lambda: b_clicked(2))
b3 = Button(root, text='3', padx=40, pady=20, command=lambda: b_clicked(3))
b4 = Button(root, text='4', padx=40, pady=20, command=lambda: b_clicked(4))
b5 = Button(root, text='5', padx=40, pady=20, command=lambda: b_clicked(5))
b6 = Button(root, text='6', padx=40, pady=20, command=lambda: b_clicked(6))
b7 = Button(root, text='7', padx=40, pady=20, command=lambda: b_clicked(7))
b8 = Button(root, text='8', padx=40, pady=20, command=lambda: b_clicked(8))
b9 = Button(root, text='9', padx=40, pady=20, command=lambda: b_clicked(9))
b0 = Button(root, text='0', padx=40, pady=20, command=lambda: b_clicked(0))

badd = Button(root, text='+', padx=39, pady=20, command=b_add)
bsub = Button(root, text='-', padx=41, pady=20, command=b_sub)
bmul = Button(root, text='*', padx=40, pady=20, command=b_mul)
bdiv = Button(root, text='/', padx=41, pady=20, command=b_div)

bequal = Button(root, text='=', padx=91, pady=20, command=b_equal)
bclear = Button(root, text='Clear', padx=79, pady=20, command=b_clear)

# Put the Buttons on the screen

b1.grid(row=3, column=0)
b2.grid(row=3, column=1)
b3.grid(row=3, column=2)

b4.grid(row=2, column=0)
b5.grid(row=2, column=1)
b6.grid(row=2, column=2)

b7.grid(row=1, column=0)
b8.grid(row=1, column=1)
b9.grid(row=1, column=2)

b0.grid(row=4, column=0)

badd.grid(row=5, column=0)
bsub.grid(row=6, column=0)
bmul.grid(row=6, column=1)
bdiv.grid(row=6, column=2)
bequal.grid(row=4, column=1, columnspan=2)
bclear.grid(row=5, column=1, columnspan=2)






root.mainloop()
danke schon mal für alle Antworten.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist doch recht klar in der Fehlermeldung beschrieben:

ValueError: invalid literal for int() with base 10: ''

Der leere String kann nicht zu einer Zahl werden. Was ja nicht verwunderlich ist - was sollte der dann auch sein?
Benutzeravatar
Gödel
User
Beiträge: 20
Registriert: Samstag 16. April 2022, 15:32

Wow. Ich bin echt blöd, wie kann man sowas übersehen?? Danke!
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Jeder fängt klein an. Wird schon.
Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Gödel: Vielleicht solltest Du nicht gleich mit GUI-Programmierung anfangen. Der Code ist noch ziemlich weit von objektorientierter Programmierung (OOP) entfernt, und die ist eigentlich Voraussetzung für GUI-Programmierung mit den meisten Rahmenwerken, und `tkinter` gehört dazu. Für so einen Taschenrechner braucht man Zustand den man sich über Aufrufe hinweg merken muss, und da man keine globalen Variablen verwendet, läuft das auf ein Objekt mit Zustand hinaus, also eine eigene Klasse.

Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 140 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen.

Namen sollten nicht nur aus einem Buchstaben bestehen oder aus kryptischen Abkürzungen. Auch keine kryptischen Prä- oder Suffixe. Der Name soll dem Leser vermitteln was der Wert dahinter bedeutet, nicht ein Rätsel sein das man erst lösen muss.

Man numeriert keine Namen durch. Dann will man entweder bessere Namen oder eine Datenstruktur. Oft eine Liste. Oder auch gar keine verschiedenen Namen. `b1` bis `b0` beispielsweise bräuchte man gar nicht wenn man den jeweiligen Button auch gleich platzieren würde. Da könnte man eine Schleife über eine Datenstruktur schreiben, statt für jeden Button Code hin zu schreiben. In dem Fall ist auch ein Blick auf `functools.partial()` statt ``lambda``-Ausdrücken empfehlenswert.

Das `math`-Modul wird importiert, aber dann wird der Name `math` auf Modulebene später an Zeichenketten gebunden. Das ist verwirrend. Weder das `math`-Modul, noch das daraus noch einmal explizit importierte `sqrt()` wird irgendwo verwendet.

Beim prüfen von `math` wird immer ``if`` verwendet. Da das aber immer nur *einen* der Werte annehmen kann, wäre hier ``if``/``elif`` wesentlich sinnvoller, vor allem auch weil man am Ende mit einem ``else`` dann auch auf den Fall reagieren kann bei dem `math` *keinen* der Werte hat.

Der Code wäre einfacher wenn man statt einer Zeichenkette mit der Bezeichnung der Rechenoperation und vielen ``if``-Abfragen die Operation selbst in Form einer Funktion in einer Variablen vermerken würde. Die ganzen Operatoren von Python gibt es im `operator`-Modul als Funktionen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Gödel
User
Beiträge: 20
Registriert: Samstag 16. April 2022, 15:32

@__blackjack__
hi blackjack, dass ich nicht gleich mit GUI Programmierung anfangen sollte stimmt wahrscheinlich, allerdings kann ich mir so die Sachen eben graphisch darstellen, was es für mich einfacher macht zu lernen.
Deinen Vorschlag mit Klassen zu arbeiten hab ich befolgt/ zumindest versucht, es bestimmt immer noch nicht super gut und von perfekt weit entfernt, aber es hat den Code wie du es gesagt hast verständlicher gemacht, auch das mit if und elif hab ich verbessert(zumindest versucht).

Deshalb danke für die Tips/Ratschläge
Antworten