Programmoptimierung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Nerdy_5
User
Beiträge: 5
Registriert: Sonntag 30. Juni 2019, 12:53

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]
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

*-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.
Nerdy_5
User
Beiträge: 5
Registriert: Sonntag 30. Juni 2019, 12:53

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?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

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.
Nerdy_5
User
Beiträge: 5
Registriert: Sonntag 30. Juni 2019, 12:53

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()
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

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.
Nerdy_5
User
Beiträge: 5
Registriert: Sonntag 30. Juni 2019, 12:53

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?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

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()
Nerdy_5
User
Beiträge: 5
Registriert: Sonntag 30. Juni 2019, 12:53

OK, Dankeschön
Antworten