Hallo Leute,
ich bin neu was die Programmierung mit Python betrifft und deswegen hab ich eine Frage. Im nachstehenden Programmcode habe ich 10 Entry Fenster auf einer GUI plaziert, weil ich mit jedem Wert einzeln arbeiten muss. Ich würde das ganze gerne verkürzen durch eine "for" oder "while" -Schleife. Es muss ja lediglich der Index geändert werden. Allerdings weiß ich nicht wie.. Ich hoffe ihr könnt mir helfen. Danke im vorraus.
Hier der Code:
[from tkinter import *
# Fenster erstellen
fenster = Tk()
fenster.title("GUI - Abschlussprojekt")
fenster.geometry("800x600")
#Eingabe x erstellen
eingabe_x1=Entry(fenster)
eingabe_x1.grid(row=2, column=1, padx=5, pady=5)
eingabe_x2=Entry(fenster)
eingabe_x2.grid(row=3, column=1, padx=5, pady=5)
eingabe_x3=Entry(fenster)
eingabe_x3.grid(row=4, column=1, padx=5, pady=5)
eingabe_x4=Entry(fenster)
eingabe_x4.grid(row=5, column=1, padx=5, pady=5)
eingabe_x5=Entry(fenster)
eingabe_x5.grid(row=6, column=1, padx=5, pady=5)
eingabe_x6=Entry(fenster)
eingabe_x6.grid(row=7, column=1, padx=5, pady=5)
eingabe_x7=Entry(fenster)
eingabe_x7.grid(row=8, column=1, padx=5, pady=5)
eingabe_x8=Entry(fenster)
eingabe_x8.grid(row=9, column=1, padx=5, pady=5)
eingabe_x9=Entry(fenster)
eingabe_x9.grid(row=10, column=1, padx=5, pady=5)
eingabe_x10=Entry(fenster)
eingabe_x10.grid(row=11, column=1, padx=5, pady=5)
#Eingabe y erstellen
eingabe_y1=Entry(fenster)
eingabe_y1.grid(row=2, column=2, padx=5, pady=5)
eingabe_y2=Entry(fenster)
eingabe_y2.grid(row=3, column=2, padx=5, pady=5)
eingabe_y3=Entry(fenster)
eingabe_y3.grid(row=4, column=2, padx=5, pady=5)
eingabe_y4=Entry(fenster)
eingabe_y4.grid(row=5, column=2, padx=5, pady=5)
eingabe_y5=Entry(fenster)
eingabe_y5.grid(row=6, column=2, padx=5, pady=5)
eingabe_y6=Entry(fenster)
eingabe_y6.grid(row=7, column=2, padx=5, pady=5)
eingabe_y7=Entry(fenster)
eingabe_y7.grid(row=8, column=2, padx=5, pady=5)
eingabe_y8=Entry(fenster)
eingabe_y8.grid(row=9, column=2, padx=5, pady=5)
eingabe_y9=Entry(fenster)
eingabe_y9.grid(row=10, column=2, padx=5, pady=5)
eingabe_y10=Entry(fenster)
eingabe_y10.grid(row=11, column=2, padx=5, pady=5)
#Bestandteile auf Oberfläche
lab = Label(fenster, text="x")
lab.grid(row=1, column=1)
lab2 = Label(fenster, text="y")
lab2.grid(row=1, column=2)
#Funktionen definieren
def Flaecheninhalt():
x1=float(eingabe_x1.get())
x2=float(eingabe_x2.get())
x3=float(eingabe_x3.get())
x4=float(eingabe_x4.get())
x5=float(eingabe_x5.get())
x6=float(eingabe_x6.get())
x7=float(eingabe_x7.get())
x8=float(eingabe_x8.get())
x9=float(eingabe_x9.get())
x10=float(eingabe_x10.get())
y1=float(eingabe_y1.get())
y2=float(eingabe_y2.get())
y3=float(eingabe_y3.get())
y4=float(eingabe_y4.get())
y5=float(eingabe_y5.get())
y6=float(eingabe_y6.get())
y7=float(eingabe_y7.get())
y8=float(eingabe_y8.get())
y9=float(eingabe_y9.get())
y10=float(eingabe_y10.get())
fläche=0.5*((x2*(y3-y1))+(x3*(y4-y2))+(x4*(y5-y3))+(x5*(y6-y4))+(x6*(y7-y5))+(x7*(y8-y6))+(x8*(y9-7))+(x9*(y10-y8)))
ausgabe.configure(text=("Flächeninhalt:=",fläche))
def close_fenster():
fenster.destroy()
#Buttons erstellen
Button1 = Button(fenster, text="Berechnen", command=Flaecheninhalt)
Button1.grid(row=12, column=1 , padx=5, pady=5)
Button2 = Button(fenster, text="Beenden", command=close_fenster)
Button2.grid(row=12, column=2, pady=5)
lab3=Label(fenster)
lab3.grid(row=4, column=2)
ausgabe=Label(fenster)
ausgabe.grid(row=1, column=4)
mainloop()][/code]
Programmoptimierung
*-Importe sind schlecht, bei tkinter holst Du Dir fast 200 Namen in den eigenen Namensraum. Üblicherweise wird ›import tkinter as tk‹ benutzt und alle Namen über tk.xyz angesprochen.
Auf oberste Ebene sollte kein ausführbarer Code stehen, die ganze GUI-Ergeugung muß also in eine Funktion wandern. Damit wird auch verhindert, dass man wild auf globale Variablen zugeifen kann.
Alles was eine Funktion braucht, sollte sie über ihre Argumente bekommen, bei Flaecheninhalt sind das 21 Argumente! Das ist für jede Funktion viel zu viel. Jedes nicht triviale GUI-Programm braucht Klassendefinitionen.
Für Dein konkretes Problem mußt Du lernen, wie man Listen verwendet und alle Eingabefelder in zwei Listen packen.
Auf oberste Ebene sollte kein ausführbarer Code stehen, die ganze GUI-Ergeugung muß also in eine Funktion wandern. Damit wird auch verhindert, dass man wild auf globale Variablen zugeifen kann.
Alles was eine Funktion braucht, sollte sie über ihre Argumente bekommen, bei Flaecheninhalt sind das 21 Argumente! Das ist für jede Funktion viel zu viel. Jedes nicht triviale GUI-Programm braucht Klassendefinitionen.
Für Dein konkretes Problem mußt Du lernen, wie man Listen verwendet und alle Eingabefelder in zwei Listen packen.
Gut, danke für deine Ratschläge. Das wir mit *-Importe arbeiten, liegt an der Vorgabe meines Dozenten (habe mich aber auch schon auf youtube informiert wie man es anders besser machen kann). Ich habe auch schon Listen behandelt und versucht die Eingabefelder in eine Liste zu packen, jedoch wird dadurch die Funktion für den Flächeninhalt nicht wirklich kleiner. Wir müssen diesen über eine Gaußformel berechnen und dadurch bleibt ja die Anzahl an Argumenten gleich..oder gibt es irgendwelche Anweisungen wie ich mit Summenformeln das Ganze verbessern kann?
Irgendwie fehlt mir in der Formel noch ein `x1` und ein weiterer Fehler hätte sich erst gar nicht eingeschlichen, wenn Du nicht alles händisch eintippen müßtest. Erster Schritt wäre, Listen für die Eingabefelder zu verwenden, und wenn das umgestzt ist, kannst Du Dir überlegen, wie man das mit Schleifen eleganter machen könnte. Um zu helfen, müßte man aber den geänderten Code sehen.
Ja, ich habe jetzt das Programm komplett überarbeitet und anhand von Listen das ganze vereinfacht. Dennoch hbae ich ein Problem mit dem ändern des Datentyps meiner Eingaben. Er gibt immer die Fehlermeldung "can't convert string to float" also muss es einen Fehler in meiner Schleife geben. Mein Code sieht jetzt wie folgt aus:
Code: Alles auswählen
from tkinter import *
#--------------------------------------------Fenster erstellen-----------------------------------------------
fenster = Tk()
fenster.title("GUI - Abschlussprojekt")
fenster.geometry("800x600")
#------------------------------------------------Funktionen definieren---------------------------------------
def Flaecheninhalt():
flaeche=0
for i in range (0,9):
Lx[i]=float(Lx[i])
Ly[i]=float(Ly[i])
for i in range (0,8):
flaeche=flaeche+(Lx[i]*(Ly[i+1]-Ly[i]))
flaeche_gesamt=0.5*fläche
ausgabeA.configure(text=("Flächeninhalt:=",flaeche_gesamt))
def STatMoment():
Sy=0
Sz=0
for i in range (0,9):
Lx[i]=float(Lx[i])
Ly[i]=float(Ly[i])
for i in range (0,8):
Sy=Sy+((Ly[i+1]*Lx[i]-Ly[i]*Lx[i+1])*(Lx[i+1]+Lx[i]))
Sy_gesamt=1/6*Sy
ausgabeSy.configure(text=("Statisches Moment Sy=",Sy_gesamt))
for i in range (0,8):
Sz=Sz+((Ly[i+1]*Lx[i]-Ly[i]*Lx[i+1])*(Ly[i+1]+Ly[i]))
Sz_gesamt=1/6*Sz
ausgabeSz.configure(text=("Statisches Moment Sz=",Sz_gesamt))
def close_fenster():
fenster.destroy()
#-----------------------------------------GUI-Elemente erstellen--------------------------------------------
#Buttons
Button1 = Button(fenster, text="Berechnen", command=Flaecheninhalt)
Button2 = Button(fenster, text="Beenden", command=close_fenster)
#Beschriftung der Eingabefelder
lab = Label(fenster, text="x")
lab2 = Label(fenster, text="y")
#Einabefelder x-Koordinaten
eingabe_x0=Entry(fenster)
eingabe_x1=Entry(fenster)
eingabe_x2=Entry(fenster)
eingabe_x3=Entry(fenster)
eingabe_x4=Entry(fenster)
eingabe_x5=Entry(fenster)
eingabe_x6=Entry(fenster)
eingabe_x7=Entry(fenster)
eingabe_x8=Entry(fenster)
eingabe_x9=Entry(fenster)
#Eingabefelder y-Koordinaten
eingabe_y0=Entry(fenster)
eingabe_y1=Entry(fenster)
eingabe_y2=Entry(fenster)
eingabe_y3=Entry(fenster)
eingabe_y4=Entry(fenster)
eingabe_y5=Entry(fenster)
eingabe_y6=Entry(fenster)
eingabe_y7=Entry(fenster)
eingabe_y8=Entry(fenster)
eingabe_y9=Entry(fenster)
#Ausgabefelder
ausgabeA=Label(fenster)
ausgabeSy=Label(fenster)
ausgabeSz=Label(fenster)
ausgabeSP=Label(fenster)
#--------------------------------------------------Widgets platzieren----------------------------------------
#Buttons
Button1.grid(row=12, column=1 , padx=5, pady=5)
Button2.grid(row=12, column=2, pady=5)
#Beschriftung
lab.grid(row=1, column=1)
lab2.grid(row=1, column=2)
#Ausgabefelder
ausgabeA.grid(row=1, column=4)
ausgabeSy.grid(row=2, column=4)
ausgabeSz.grid(row=3, column=4)
ausgabeSP.grid(row=4, column=4)
#Eingabewerte x
eingabe_x0.grid(row=2, column=1, padx=5, pady=5)
eingabe_x1.grid(row=3, column=1, padx=5, pady=5)
eingabe_x2.grid(row=4, column=1, padx=5, pady=5)
eingabe_x3.grid(row=5, column=1, padx=5, pady=5)
eingabe_x4.grid(row=6, column=1, padx=5, pady=5)
eingabe_x5.grid(row=7, column=1, padx=5, pady=5)
eingabe_x6.grid(row=8, column=1, padx=5, pady=5)
eingabe_x7.grid(row=9, column=1, padx=5, pady=5)
eingabe_x8.grid(row=10, column=1, padx=5, pady=5)
eingabe_x9.grid(row=11, column=1, padx=5, pady=5)
#Eingabewerte y
eingabe_y0.grid(row=2, column=2, padx=5, pady=5)
eingabe_y1.grid(row=3, column=2, padx=5, pady=5)
eingabe_y2.grid(row=4, column=2, padx=5, pady=5)
eingabe_y3.grid(row=5, column=2, padx=5, pady=5)
eingabe_y4.grid(row=6, column=2, padx=5, pady=5)
eingabe_y5.grid(row=7, column=2, padx=5, pady=5)
eingabe_y6.grid(row=8, column=2, padx=5, pady=5)
eingabe_y7.grid(row=9, column=2, padx=5, pady=5)
eingabe_y8.grid(row=10, column=2, padx=5, pady=5)
eingabe_y9.grid(row=11, column=2, padx=5, pady=5)
#---------------------------------------------------Hauptprogramm--------------------------------------------
#Eingabewerte in Listen erfassen
Lx=[eingabe_x0.get(),eingabe_x1.get(),eingabe_x2.get(),eingabe_x3.get(),eingabe_x4.get(),eingabe_x5.get(),eingabe_x6.get(),eingabe_x7.get(),eingabe_x8.get(),eingabe_x9.get()]
Ly=[eingabe_y0.get(),eingabe_y1.get(),eingabe_y2.get(),eingabe_y3.get(),eingabe_y4.get(),eingabe_y5.get(),eingabe_y6.get(),eingabe_y7.get(),eingabe_y8.get(),eingabe_y9.get()]
mainloop()
Statt Kommentare mit vielen --- mußt Du Funktionen definieren, die sagen dann über ihren Namen genauso viel was sie machen und haben den Vorteil, dass Du keine Globalen Variablen mehr verwenden kannst.
Funktionen bekommen alles, was sie brauchen über ihre Argumente. Über einen Index zu iterieren ist schelcht, weil Du ja wissen mußt, wie viele Elemente die Listen haben und umständlich, da das iterieren über die Elemente viel klarer ist. Den Listeninhalt ändert man auch nicht, sondern erzeugt eine neue Liste, weil Du sonst unkontrollierbare Nebenwirkungen hast.
Die Entry-Felder solltest Du gleich in Listen packen.
Den Inhalt der Eingabefelder gleich beim Start abzufragen ist quatsch, weil da ja noch niemand die Chance hatte, da was einzutragen.
Funktionen bekommen alles, was sie brauchen über ihre Argumente. Über einen Index zu iterieren ist schelcht, weil Du ja wissen mußt, wie viele Elemente die Listen haben und umständlich, da das iterieren über die Elemente viel klarer ist. Den Listeninhalt ändert man auch nicht, sondern erzeugt eine neue Liste, weil Du sonst unkontrollierbare Nebenwirkungen hast.
Die Entry-Felder solltest Du gleich in Listen packen.
Den Inhalt der Eingabefelder gleich beim Start abzufragen ist quatsch, weil da ja noch niemand die Chance hatte, da was einzutragen.
Danke für die schnelle Antwort, also sollte ich nicht Versuchen den Elementen in meiner Liste einen neuen Datentyp zu geben sondern eine neue Liste erstellen die nur diesen Datentyp vorweist? Und wie soll ich ohne Index arbeiten wenn ich ja für die Formeln einzelne Werte aus der Liste brauche? (Könntet du evtl. Ein Beispiel angeben)
Bezüglich der Eingabefelder, kann man das doch nicht so einfach machen (diese in eine Liste packen), weil man sie doch noch auf der GUI platzieren muss oder sehe ich das falsch?
Bezüglich der Eingabefelder, kann man das doch nicht so einfach machen (diese in eine Liste packen), weil man sie doch noch auf der GUI platzieren muss oder sehe ich das falsch?
Zum Beispiel könnte das so aussehen:
Code: Alles auswählen
import tkinter as tk
def calculate_area(x_entries, y_entries, ausgabe):
lx = [float(e.get()) for e in x_entries]
ly = [float(e.get()) for e in y_entries]
flaeche=0
for x, y1, y2 in zip(lx, ly[1:], ly):
flaeche += x * (y1-y2)
ausgabe['text'] = "Flächeninhalt:={}".format(flaeche/2)
def create_window():
fenster = tk.Tk()
fenster.title("GUI - Abschlussprojekt")
tk.Label(fenster, text="x").grid(row=1, column=1)
x_entries = []
for k in range(2, 12):
entry = tk.Entry(fenster)
entry.grid(row=k, column=1, padx=5, pady=5)
x_entries.append(entry)
tk.Label(fenster, text="y").grid(row=1, column=2)
y_entries = []
for k in range(2, 12):
entry = tk.Entry(fenster)
entry.grid(row=k, column=2, padx=5, pady=5)
y_entries.append(entry)
ausgabe_a = tk.Label(fenster)
ausgabe_a.grid(row=1, column=4)
ausgabe_sy = tk.Label(fenster)
ausgabe_sy.grid(row=2, column=4)
ausgabe_sz = tk.Label(fenster)
ausgabe_sz.grid(row=3, column=4)
ausgabe_sp = tk.Label(fenster)
ausgabe_sp.grid(row=4, column=4)
tk.Button(fenster, text="Berechnen", command=partial(calculate_area,
x_entries, y_entries, ausgabe_a
)).grid(row=12, column=1 , padx=5, pady=5)
tk.Button(fenster, text="Beenden", command=fenster.destroy).grid(row=12, column=2, pady=5)
return fenster
def main():
fenster = create_window()
fenster.mainloop()
if __name__ == '__main__':
main()