@kakashi: Numpy wird importiert aber nicht verwendet.
Man sollte es mit Leerzeilen nicht übertreiben, aber ein komplettes Programm ohne eine einzige Leerzeile ist nicht gut lesbar. Nach Kommas, um binäre Operatoren, und um das Gleichheitszeichen bei Zuweisungen ausser bei Schlüsselwort-Argumenten erhöhen Leerzeichen die Lesbarkeit.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Womit `main` für das Hauptfenster kein guter Name ist. Traditionell heisst das `Tk`-Objekt `root`, man könnte es aber auch `main_window` nennen.
Das erzeugen und anordnen von Anzeigeelementen sollte man nicht so voneinander trennen und das Erzeugen auch nicht nach dem Typ der Anzeigeelemente sortieren. Das macht es unnötig schwer am Code den GUI-Aufbau nachzuvollziehen und es macht auch unnötig Arbeit wenn man Teile der GUI-Erstellung in Funktionen oder eigene Klassen auslagern möchte, wenn man sich dann aus dem langen Code erst alles zusammensuchen muss, weil da nicht zusammen steht was zusammen gehört.
Beim Erzeugen der Eingabefelder machen die `insert()`-Aufrufe überhaupt keinen Sinn. Die fügen jeweils in ein leeres Feld an der 5. Position *nichts* ein. Die Felder bleiben dadurch also wie sie sind.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).
Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. Wenn man `label` meint, sollte man nicht nur `lbl` schreiben. Und die Reihenfolge `label_normalkraft` wäre auch eher nur für Yoda okay, normale Menschen sagen dazu `normalkraft_label`.
Man muss aber auch nicht jedes Zwischenergebnis an einen Namen binden wenn man das danach nie wieder verwendet.
Man nummeriert keine Namen. Entweder will man sich dann bessere Namen überlegen, oder gar keine Einzelnamen sondern eine Datenstruktur. Oft eine Liste. Das wäre bei den Ausgabe-Label eine Option.
Im `tkinter`-Modul gibt es für Zeichenketten wie "center" Konstanten die man verwenden sollte.
Funktionen (und Methoden) werden üblicherweise nach der Tätigkeit benannt die sie durchführen, damit man sie von eher passiven Werten unterscheiden kann. `Eckspannungsberechnung()` → `berechne_eckspannungen()`.
Funktionen und Methoden bekommen alles was sie ausser Konstanten benötigen als Argumet(e) übergeben. Die `berechne_eckspannungen()`-Funktion braucht also sowohl die Eingabefelder als auch die Ausgabe-Label als Argumente.
Der ``try``/``except``-Block steht an der falschen Stelle und man sollte keine nackten ``except``\s ohne konkrete Ausnahemen die man auch tatsächlich so behandeln kann verwenden. Der Benutzer wird beispielsweise verwirrt sein wenn er Zahlen eingibt und dann die Meldung "Zahlen eingeben" bekommt. Die wird beispielsweise ausgegeben wenn Eingabewerte 0 waren und dadurch ein `ZeroDivisionError` ausgelöst wurde.
Da wo die Meldung Sinn machen würde, wird die dazugehörige Ausnahme gar nicht behandelt. Nämlich ein `ValueError` der beim Umwandeln der Texte aus den Eingabefeldern in Gleitkommazahlen auftreten kann.
Wenn man sich die Rechnungen für S1 bis S4 anschaut, dann unterscheiden die sich nur durch jeweils zwei Rechenoperationen:
Code: Alles auswählen
S1 = N / (bx * by) + N * ex / Wy + N * ey / Wx
S2 = N / (bx * by) - N * ex / Wy + N * ey / Wx
S3 = N / (bx * by) - N * ex / Wy - N * ey / Wx
S4 = N / (bx * by) + N * ex / Wy - N * ey / Wx
# ^ ^
# 1 2
Diesen Unterschied kann man als Daten in eine Liste herausziehen und die Ergebnisse mit einer Schleife erstellen. Was auch zu den Ergebnis-Labeln in einer Liste passen würde.
Das zusammenstückeln von Zeichenketten und Werten mittels ``+`` und `str()` ist eher BASIC als Python. Dafür gibt es die `format()`-Methode auf Zeichenketten und f-Zeichenkettenliterale.
Zwischenstand:
Code: Alles auswählen
#!/usr/bin/env python3
import tkinter as tk
from functools import partial
from operator import add, sub
def berechne_eckspannungen(
normalkraft_entry,
laenge_a_entry,
laenge_b_entry,
ausmitte_x_entry,
ausmitte_y_entry,
ergebnis_labels,
):
try:
normalkraft = float(normalkraft_entry.get())
laenge_a = float(laenge_a_entry.get())
laenge_b = float(laenge_b_entry.get())
ausmitte_x = float(ausmitte_x_entry.get())
ausmitte_y = float(ausmitte_y_entry.get())
except ValueError:
for ergebnis_label in ergebnis_labels:
ergebnis_label["text"] = "Zahlen eingeben"
else:
try:
for (
nummer,
(ergebnis_label, (operation_a, operation_b)),
) in enumerate(
zip(
ergebnis_labels,
[(add, add), (sub, add), (sub, sub), (add, sub)],
),
1,
):
ergebnis = operation_a(
normalkraft / (laenge_a * laenge_b),
operation_b(
6
* normalkraft
* ausmitte_x
/ (laenge_b * laenge_a ** 2),
6
* normalkraft
* ausmitte_y
/ (laenge_a * laenge_b ** 2),
),
)
ergebnis_label["text"] = f"S{nummer} = {ergebnis} kN/m^2"
except ZeroDivisionError:
for ergebnis_label in ergebnis_labels:
ergebnis_label["text"] = "Teilen durch 0 nicht möglich"
def main():
root = tk.Tk()
root.title("Spannungstrapezverfahren")
entry_options = {"width": 5, "justify": tk.CENTER}
tk.Label(root, text="Normalkraft in kN/m^2:").pack()
normalkraft_entry = tk.Entry(root, **entry_options)
normalkraft_entry.pack()
tk.Label(root, text="Länge a in m eingeben:").pack()
laenge_a_entry = tk.Entry(root, **entry_options)
laenge_a_entry.pack()
tk.Label(root, text="Länge b in m eingeben:").pack()
laenge_b_entry = tk.Entry(root, **entry_options)
laenge_b_entry.pack()
tk.Label(root, text="Ausmitte in x-Richtung in m eingeben:").pack()
ausmitte_x_entry = tk.Entry(root, **entry_options)
ausmitte_x_entry.pack()
tk.Label(root, text="Ausmitte in y-Richtung in m eingeben:").pack()
ausmitte_y_entry = tk.Entry(root, **entry_options)
ausmitte_y_entry.pack()
berechnen_button = tk.Button(
root, text="Berechne Eckspannung S1, S2, S3, S4"
)
berechnen_button.pack()
ergebnis_labels = list()
for _ in range(4):
label = tk.Label(root)
label.pack()
ergebnis_labels.append(label)
berechnen_button["command"] = partial(
berechne_eckspannungen,
normalkraft_entry,
laenge_a_entry,
laenge_b_entry,
ausmitte_x_entry,
ausmitte_y_entry,
ergebnis_labels,
)
tk.Button(root, text="Beenden", command=root.quit).pack()
root.mainloop()
if __name__ == "__main__":
main()