GUI für ein Bierbrau-Programm

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
calli
User
Beiträge: 3
Registriert: Montag 13. Mai 2019, 00:54

Hallo zusammen!

Ich habe meinem Vater ein Bierbrauset zum Geburtstag geschenkt und würde nun gerne ein Programm mit dem Raspberry Pi schreiben, um die Temperaturen zu regeln.
Die Oberfläche habe ich bereits erstellt und diese gefällt mir so auch schon ganz gut.
Auch die zwei Temperatursensoren konnte ich schon einlesen und mit Knopfdruck in bestimmten Zeitabständen abfragen.
Die GPIO Ausgänge kann ich per Knopfdruck auch schon schalten.

Nun stehe ich aber vor folgendem Problem:
-Per Knopfdruck (EinmaischenButton.Botton) soll nun ein Timer mit der eingegebenen Zeit (t1) gestartet werden.
Während der Timer abläuft soll die Temperatur mit der eingegebenen Sollwert der Temperatur (temp1) vergleichen werden.
Sollte die Temperaturmessung den Sollwert (temp1) unterschreiten, soll das Relais schalten (GPIO Ausgang 11).
Nun fehlt es mir leider an Werkzeug, um diese Funktion umzusetzen. Wenn ich eine If Abfrage starte habe ich das Problem, das nur bei Knopfdruck die Temperatur ausgelesen wird, dann aber nicht mehr. Zudem habe ich das Problem den Timer und die Temperaturabfrage gleichzeitig laufen zu lassen.

Für einen Tipp, wie man dies umsetzen könnte wäre ich sehr dankbar!

Hier noch der bestehende Code, falls jemand mal ein ähnliches Projekt starten will ;-)

Code: Alles auswählen

from Tkinter import *
import tkFont
import RPi.GPIO as GPIO
import sys, time, os, subprocess

GPIO.setmode(GPIO.BOARD) 	#GPIO werden aktiviert
GPIO.setup(11, GPIO.OUT) 	#GPIO Augang wird aktiviert
GPIO.output(11, GPIO.LOW)  	#GPIO Augang wird auf 0 gesetzt
    
root = Tk() # Fenster erstellen
root.wm_title("Hofbrauhaus Franz") # Fenster Titel

H=10

def Einmaischen():
    print("Einmaischen gestartet")
    
    if GPIO.input(11):
        
        GPIO.output(11,GPIO.LOW)
        EinmaischenButton["text"]="Einmaischen AN"
        EinmaischenButton["background"]="red"
    
    else:
        GPIO.output(11,GPIO.HIGH)
        EinmaischenButton["text"]="Einmaischen AUS"
        EinmaischenButton["background"]="green"
       
def Rast1():
    print("1. Rast gestartet")
    if GPIO.input(11):
        GPIO.output(11,GPIO.LOW)
        Rast1Button["text"]="1. Rast AN"
        Rast1Button["background"]="red"
    else:
        GPIO.output(11,GPIO.HIGH)
        Rast1Button["text"]="1. Rast AUS"
        Rast1Button["background"]="green"
        
def Rast2():
    print("2. Rast gestartet")
    if GPIO.input(11):
        GPIO.output(11,GPIO.LOW)
        Rast2Button["text"]="2. Rast AN"
        Rast2Button["background"]="red"
    else:
        GPIO.output(11,GPIO.HIGH)
        Rast2Button["text"]="2. Rast AUS"
        Rast2Button["background"]="green"
            
def Abmaischen():
    print("Abmaischen gestartet")
    if GPIO.input(11):
        GPIO.output(11,GPIO.LOW)
        AbmaischenButton["text"]="Abmaischen AN"
        AbmaischenButton["background"]="red"
    else:
        GPIO.output(11,GPIO.HIGH)
        AbmaischenButton["text"]="Abmaischen AUS"
        AbmaischenButton["background"]="green"
        
def Kochen():
    print("Kochen gestartet")
    if GPIO.input(11):
        GPIO.output(11,GPIO.LOW)
        KochenButton["text"]="Kochen AN"
        KochenButton["background"]="red"
    else:
       # temp11=float(temp5.get())
       # Temp11.config (text=temp11)
        GPIO.output(11,GPIO.HIGH)
        KochenButton["text"]="Kochen AUS"
        KochenButton["background"]="green"
def exitProgram():
    print ("Verlassen Knopf gedrueckt")
    GPIO.cleanup()
    root.quit()
    
def aktuelleTemperatur():
    if H>1:
        TempButton["text"]="Temperaturmessung AN"
        TempButton["background"]="green"
   
        #Sensor 1a uslesen: 1-wire Slave Datei lesen
        file1 = open('/sys/bus/w1/devices/28-02131d99f4aa/w1_slave')
        filecontent1 = file1.read()
        file1.close()
        #Sensor 2 auslesen: 1-wire Slave Datei lesen
        file2 = open('/sys/bus/w1/devices/28-02131d9e7baa/w1_slave')
        filecontent2 = file2.read()
        file2.close()
     
        # Temperaturwerte Sensor 1 auslesen und konvertieren
        stringvalue1 = filecontent1.split("\n")[1].split(" ")[9]
        temperature1 = float(stringvalue1[2:]) / 1000
        # Temperaturwerte Sensor 2 auslesen und konvertieren
        stringvalue2 = filecontent2.split("\n")[1].split(" ")[9]
        temperature2 = float(stringvalue2[2:]) / 1000
        
        #Mittelwertberechnung Temperatur
        rueckgabewertM=(temperature1+temperature2)/2
        
        #Differenz Temperatur
        rueckgabewertD=(temperature2-temperature1)
        
        # Temperatur Sensor 1 ausgeben
        rueckgabewert1 = '%6.2f' % temperature1 
        Temperatur1.config(text=rueckgabewert1)
        # Temperatur Sensor 2 ausgeben
        rueckgabewert2 = '%6.2f' % temperature2 
        Temperatur2.config(text=rueckgabewert2)
        
        #Mittelwert berechnen:
        rueckgabewertMW = '%6.2f' % rueckgabewertM 
        TemperaturMW.config(text=rueckgabewertMW)
        #Differenz berechnen:
        rueckgabewertDW = '%6.2f' % rueckgabewertD 
        TemperaturDW.config(text=rueckgabewertDW)
        
    else:
        TempButton["text"]="Temperaturmessung AUS"
        TempButton["background"]="red"
    root.after(100, aktuelleTemperatur)
         
             
    #  Frame oben
    topFrame = Frame(root) # Frame initialisieren
    topFrame.grid(row=0, rowspan=3, column=0, columnspan=2) # Relative Position und 
    Seitenabstand (padding) angeben
    
    # Hier kommen die Elemente des linken Frames rein   
    topLabel1 = Label(topFrame, text= "HOFBRAUHAUS DITTMANN \n", font=('bold'))
    topLabel1.grid(row=0, column=0, columnspan=2)
    topLabel2 = Label(topFrame, text="Heute brauen wir ein Helles! \n \n \n")
    topLabel2.grid(row=1, column=0, columnspan=2)
    topLabel3 = Label(topFrame, text="----------------------------------------- \n \n \n")
    topLabel3.grid(row=2, column=0,columnspan=2)
     
    #  Frame oben
    image1 = PhotoImage(file='Bier1')
    panel1 = Label(root, image = image1)
    panel1.grid(row=0,rowspan=3, column=2, columnspan=3, sticky=W+E+N+S, padx=3, pady=3)
     
    #Frame 1.Spalte
    middleFrame1 = Frame(root)
    middleFrame1.grid(row=3, rowspan=5, column=0)
    
    #Inhalt der Frame mitte
    #Eingabe Sollwert
    Label1=Label(middleFrame1, text="Einmaischen\n")
    Label1.grid(row=3, column=0, sticky=W)
    Label1=Label(middleFrame1, text="1. Rast\n")
    Label1.grid(row=4, column=0, sticky=W)
    Label1=Label(middleFrame1, text="2. Rast\n")
    Label1.grid(row=5, column=0, sticky=W)
    Label1=Label(middleFrame1, text="Abmaischen\n")
    Label1.grid(row=6, column=0, sticky=W)
    Label1=Label(middleFrame1, text="Kochen\n")
    Label1.grid(row=7, column=0, sticky=W)
    
    #Frame 2.Spalte:
    middleFrame2 = Frame(root)
    middleFrame2.grid(row=3, rowspan=5, column=1)
    Label1=Label(middleFrame2, text="    Sollwert Temperatur:\n")
    Label1.grid(row=3, column=2, sticky=W+N)
    Label1=Label(middleFrame2, text="    Sollwert Temperatur:\n")
    Label1.grid(row=4, column=2, sticky=W+N)
    Label1=Label(middleFrame2, text="    Sollwert Temperatur:\n")
    Label1.grid(row=5, column=2, sticky=W+N)
    Label1=Label(middleFrame2, text="    Sollwert Temperatur:\n")
    Label1.grid(row=6, column=2, sticky=W+N)
    Label1=Label(middleFrame2, text="    Sollwert Temperatur:\n")
    Label1.grid(row=7, column=2, sticky=W+N)
    
    #Frame 3.Spalte:
    middleFrame3 = Frame(root)
    middleFrame3.grid(row=3, rowspan=5, column=2)
    temp1 = Entry(root)  #Einmaischen
    temp1.insert(0, 40)
    temp1.grid(row=3, column=2, sticky=N)
    temp2 = Entry(root)   #Rast1
    temp2.insert(0, 50)
    temp2.grid(row=4, column=2, sticky=N)
    temp3 = Entry(root)   #Rast2
    temp3.insert(0, 66)
    temp3.grid(row=5, column=2, sticky=N)
    temp4 = Entry(root)   #Abmaischen
    temp4.insert(0, 78)
    temp4.grid(row=6, column=2, sticky=N)
    temp5 = Entry(root)   #Kochen
    temp5.insert(0, 110)
    temp5.grid(row=7, column=2, sticky=N)
    
    #Frame 4.Spalte
    middleFrame4 = Frame(root)
    middleFrame4.grid(row=3, rowspan=5, column=3)
    Label2=Label(middleFrame4, text="   Sollwert Zeit in min:\n")
    Label2.grid(row=3, column=3, sticky=W)
    Label2=Label(middleFrame4, text="   Sollwert Zeit in min:\n")
    Label2.grid(row=4, column=3, sticky=W)
    Label2=Label(middleFrame4, text="   Sollwert Zeit in min:\n")
    Label2.grid(row=5, column=3, sticky=W)
    Label2=Label(middleFrame4, text="   Sollwert Zeit in min:\n")
    Label2.grid(row=6, column=3, sticky=W)
    Label2=Label(middleFrame4, text="   Sollwert Zeit in min:\n")
    Label2.grid(row=7, column=3, sticky=W)
    
    #Frame 5.Spalte:
    middleFrame5 = Frame(root)
    middleFrame5.grid(row=3, rowspan=5, column=4)
    t1 = Entry(root)  #Einmaischen
    t1.insert(0,10)
    t1.grid(row=3, column=4)
    t2 = Entry(root)   #Rast1
    t2.insert(0,30)
    t2.grid(row=4, column=4)
    t3 = Entry(root)   #Rast2
    t3.insert(0,60)
    t3.grid(row=5, column=4)
    t4 = Entry(root)   #Abmaischen
    t4.insert(0,10)
    t4.grid(row=6, column=4)
    t5 = Entry(root)   #Kochen
    t5.insert(0,60)
    t5.grid(row=7, column=4)
    middleFrame4 = Frame(root)
    middleFrame4.grid(row=6, column=2)
    
    #Frame 6.Spalte:
    middleFrame6 = Frame(root)
    middleFrame6.grid(row=3, rowspan=5, column=5)
    #Einmaischen Knopf
    EinmaischenButton = Button(middleFrame6, text = "Einmaischen AN", bg='red', command = 
    Einmaischen, width = 15) 
    EinmaischenButton.pack()
    #Rast1 Knopf
    Rast1Button = Button(middleFrame6, text = "Rast1 AN", bg='red', command = Rast1, width = 15)
    Rast1Button.pack()
    #Rast2 Knopf
    Rast2Button = Button(middleFrame6, text = "Rast2 AN", bg='red', command = Rast2, width = 15)
    Rast2Button.pack()
    #Abmaischen Knopf
    AbmaischenButton = Button(middleFrame6, text = "Abmaischen AN", bg='red', command = 
    Abmaischen, width = 15)
    AbmaischenButton.pack()
    #Kochen Knopf
    KochenButton = Button(middleFrame6, text = "Kochen AN", bg='red', command = Kochen, width 
    = 15)
    KochenButton.pack()
    
    #Temperatur Frame unten mittig
    TFrame = Frame(root)
    TFrame.grid(row=12, rowspan=4, column=0)
    #Temperatur Knopf
    TempButton = Button(TFrame, bg='red', text = "Temperatur anzeigen starten", command = 
    aktuelleTemperatur, height = 1, width = 20)
    TempButton.pack()
    
    #Temperatur Frame unten mittig
    TFrame1 = Frame(root)
    TFrame1.grid(row=12, rowspan=4, column=0, columnspan=6)
    #Temperaturanzeige
    LabeT1=Label(TFrame1, text="Temperatur 1:")
    LabeT1.grid(row=12, column=2, sticky=W)
    Temperatur1= Label(root, text='       Temperaturmessung')
    Temperatur1.grid(row=12, column=3)
    LabeT2=Label(TFrame1, text="Temperatur 2:")
    LabeT2.grid(row=13, column=2)
    Temperatur2 = Label(root, text='      Temperaturmessung')
    Temperatur2.grid(row=13, column=3)
    
    #Temperaturdiffernz
    LabeDW=Label(TFrame1, text="Differenz:")
    LabeDW.grid(row=14, column=2)
    TemperaturDW = Label(root, text='Temperaturdifferenz')
    TemperaturDW.grid(row=14, column=3)
    LabeMW=Label(TFrame1, text="Mittelwert:")
    LabeMW.grid(row=15, column=2)
    TemperaturMW = Label(root, text='Temperaturmittelwert')
    TemperaturMW.grid(row=15, column=3)
    Temp11 = Label(root, text='')
    Temp11.grid(row=2, column=0, sticky=E)
    
    #Frame unten mittig
    exitFrame = Frame(root)
    exitFrame.grid(row=14, rowspan=4, column=5, columnspan=6)
    
    #Verlassen Knopf
    exitButton = Button(exitFrame, text = "Programm Verlassen", bg='white', command = exitProgram, 
    height = 1, width = 15)
    exitButton.pack()
    
    root.mainloop() # GUI wird upgedated. Danach keine Elemente setzen


    
    


__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und täglich grüßt das Murmeltier.

Dein Problem musst du mit timern lösen. In Tkinter heißt das Stichwort dazu after. Und du findest dazu viele Beiträge hier.
Benutzeravatar
__blackjack__
User
Beiträge: 13112
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@calli: Das Programm enthält einen Syntaxfehler weil da ein Kommentar umgebrochen wurde und nun der umgebrochene Teil als Code interpretiert wird.

Dann ist die Einrückung falsch, denn das was da alles in `aktuelleTemperatur()` steht, gehört da ziemlich sicher nicht alles rein.

Python 2 sollte man nicht mehr für neue Projekte verwenden. Das ist ab Ende diesen Jahres am Ende seines Lebens angekommen: https://pythonclock.org/

Sternchen-Importe sind Böse™. Du holst Dir da gerade bei `Tkinter` ca. 190 Namen ins Modul von denen nur ein Bruchtteil benötigt wird. Üblich ist es `tkinter` als `tk` zu importieren und auf die Werte aus dem Modul dann über `tk.Frame` usw. zuzugreifen.

`os`, `subprocess`, `sys`, `time`, und `tkFont` werden importiert, aber nicht verwendet.

``as`` ist beim Importieren zum umbenennen da, `GPIO` wird aber gar nicht umbenannt, also ist das nicht sinnvoll. Das sollte ``from Rpi import GPIO`` heissen.

Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Funktionen und Methoden sollten alles was sie ausser Konstanten benötigen als Argument(e) übergeben bekommen. Du hast da im Grunde keine einzige Funktion im Programm die den Namen verdient. Das sind alles eher so etwas wie Sprungmarken in einem riesigen unstrukturierten Codeklumpen.

Da man sich bei GUIs Zustand über Aufrufe hinweg merken muss, kommt man bei jeder nicht-trivialen GUI nicht um objektorientierte Programmierung (OOP) herum.

Namen schreibt man in Python klein_mit_unterstrichen. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Namen sollte keine kryptischen Abkürzungen enthalten und nicht durchnummeriert sein. Ein Name soll dem Leser vermitteln was der Wert dahinter bedeutet und nicht zum rätseln zwingen. Wenn man Namen durchnummeriert, will man sich entweder bessere Namen überlegen, oder gar keine Einzelnamen/-Werte, sondern eine Datenstruktur verwenden. Oft eine Liste.

Um das ``=`` bei Zuweisungen ausserhalb von Argumentlisten, um binäre Operatoren, und nach Kommas erhöhen Leerzeichen die Lesbarkeit.

`Einmaischen()`, `Rast1()`, `Rast2()`, `Abmaischen()`, und `Kochen()` enthalten fast identischen Code. Das wäre also *eine* Funktion, der man entsprechende Argumente übergibt:

Code: Alles auswählen

def toggle_step(name, button):
    print(name, 'gestartet')  # FIXME Inhaltlich falsch!
    state = GPIO.input(11)
    GPIO.output(11, not state)
    state_text, color = [('AN', 'red'), ('AUS', 'green')][state]
    button.config(text=state_text, background=color)
Für das Einmaischen wäre der Aufruf dann `toggle_step('Einmaischen', einmaischen_button)``.
Wobei: Kann man die Schaltflächen überhaupt einzeln behandeln oder müsste man nicht dafür sorgen das immer nur eine aktiv sein kann? Der Benutzer könnte sonst ja ohne Probleme 1. Rast und Kochen gleichzeitig aktivieren.

Was auch völlig fehlt ist eine Trennung von Programmlogik und GUI. Es sollte einen Programmteil geben der keinen GUI-Code enthält und über dessen Funktionen/Klassen sich die Brauanlage steuern lässt. Damit man das einzeln testen kann und auch die GUI leicht(er) austauschen kann.

Wie man in Tk-GUIs etwas nebenläufig erledigen kann, hast Du doch eigentlich schon im Code stehen: `after()`. Man muss die Aufgabe in kurze Schritte zerlegen, die dann per `after()` zu den entsprechenden Zeitpunkten ausgeführt werden.

`GPIO.cleanup()` sollte nach der `mainloop()` stehen und das in einem `finally`-Zweig, damit es auch auf jeden Fall ausgeführt wird.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
calli
User
Beiträge: 3
Registriert: Montag 13. Mai 2019, 00:54

Hallo deets und blackjack,

vielen Dank für die vielen Hinweise und die Verbesserungen!
=> blackjack: Deine Verbesserungen habe ich versucht so weit wie möglich umzusetzen. Klasse das du dir die Zeit genommen hast!
Ich stehe noch ziemlich am Anfang (programmiere erst seit 3 Tagen mit Python) der ganzen Materie, habt ihr denn eine Empfehlung zu Literatur um sich da noch etwas besser einzulesen?
calli
User
Beiträge: 3
Registriert: Montag 13. Mai 2019, 00:54

Ich habe jetzt noch mal etwas gebastelt:
Mit der .after funktion findet nun eine kontinuierliche Temperaturabfrage statt und diese wird mit dem Sollwert verglichen.
Das Relais schaltet wie es soll.

Nun habe ich aber das Problem mit der Zeit:
Immer wenn ich die Sollwert Zeit einlese "set_time=float(t1.get())" und die "def einmaischen()" wiederhole wird ja erneut der eingetragene Sollwert eingelesen.
Ich hatte mir eigentlich überlegt, den Wert "set_time=float(t1.get())" mit 60 zu multiplizieren und dann jeden Zyklus (Zykluszeit 1 Sek) von "set_time=float(t1.get())" den Wert um 1 zu subtrahieren. Jeden Zyklus bekomme ich aber das gleiche Ergebnis :-(

Code: Alles auswählen

def einmaischen():
    print("Einmaischen gestartet")
    sollwert_temperatur=float(sollwert_temperatur_einmaischen.get()) #Aufrufen der Sollwert Temperatur
    #Aufrufen der Sollwert Zeit
    set_time=float(t1.get())   #t11 Sollwert Zeit in Minuten
    set_time=set_time*60   #t111 Sollwert Zeit in Sekunden
    #Sensor 1a uslesen: 1-wire Slave Datei lesen
    file1 = open('/sys/bus/w1/devices/28-02131d99f4aa/w1_slave')
    filecontent1 = file1.read()
    file1.close()
    #Sensor 2 auslesen: 1-wire Slave Datei lesen
    file2 = open('/sys/bus/w1/devices/28-02131d9e7baa/w1_slave')
    filecontent2 = file2.read()
    file2.close()
     
    # Temperaturwerte Sensor 1 auslesen und konvertieren
    stringvalue1 = filecontent1.split("\n")[1].split(" ")[9]
    temperatur_sensor1 = float(stringvalue1[2:]) / 1000
    # Temperaturwerte Sensor 2 auslesen und konvertieren
    stringvalue2 = filecontent2.split("\n")[1].split(" ")[9]
    temperatur_sensor2 = float(stringvalue2[2:]) / 1000
        
    
    rueckgabewertM=(temperatur_sensor1+temperatur_sensor2)/2   #Mittelwertberechnung Temperatur
    
    if temperatur_sensor2 > temperatur_sensor1:   #Differenz Temperatur
        rueckgabewertD=(temperatur_sensor2-temperatur_sensor1)
    else:
        rueckgabewertD=(temperatur_sensor1-temperatur_sensor2)
        
    if rueckgabewertD > 1:
        LabeDW["bg"]="red"
        temperatur_differenz["bg"]="red"
    else:
      	LabeDW["bg"]="green"
        temperatur_differenz["bg"]="green"
        print(rueckgabewertD)
        
    Temperatur1.config(text='%6.2f' % temperatur_sensor1 )  # Temperatur Sensor 1 ausgeben
    Temperatur2.config(text='%6.2f' % temperatur_sensor2 )  # Temperatur Sensor 2 ausgeben
        
    #Mittelwert berechnen:
    TemperaturMW.config(text='%6.2f' % rueckgabewertM)   #Mittelwert berechnen:
    temperatur_differenz.config(text='%6.2f' % rueckgabewertD)    #Differenz berechnen:
    
    print(temperatur_sensor1)
    print(sollwert_temperatur)
        
    
   	if rueckgabewertM > sollwert_temperatur:       
            GPIO.input(11)
            GPIO.output(11,GPIO.LOW)
            einmaischen_button["text"]="Einmaischen laeuft"
            einmaischen_button["background"]="red"
            #Wiederholte Abfrage:
            root.after(1000, einmaischen)
        elif rueckgabewertM < sollwert_temperatur:
            GPIO.input(11)
            GPIO.output(11,GPIO.HIGH)
            einmaischen_button["text"]="Einmaischen laeuft"
            einmaischen_button["background"]="green"
            #Wiederholte Abfrage:
            root.after(1000, einmaischen)
        elif i == 10:
            print("beendet")

Benutzeravatar
__blackjack__
User
Beiträge: 13112
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@calli: Da sind 12 Namen die einfach so aus dem Nichts kommen, in der Funktion. Wie gesagt, sollte eine Funktion alles was sie ausser Konstanten benötigt als Argument(e) übergeben bekommen. Aber 12 Argumente sind im Grunde auch zu viel. Dazu kommen dann noch die Namen die lokal verwendet werden. Das ist alles viel zu viel für eine Funktion. Die macht ja auch mehr als eine Sache. Die liest Hardware aus, rechnet Messwerte um, holt sich Werte aus der GUI, berechnet Werte auf deren Grundlage dann die GUI verändert wird, schaltet ein Relais, und versucht in den ganzen Wust dann auch noch eine Wiederholung rein zu bringen.

Reihenfolge in der die Sachen aufeinander aufbauen: Ausdrücke, Programmfluss mit Verzweigungen und Schleifen, Funktionen, Klassen, GUI-Programmierung.

Bei der GUI-Programmierung wird der Ablauf nicht mehr vom Programmierer linear programmiert, sondern der Code reagiert nur noch auf Ereignisse. Man muss Sachen die man vorher linear ausdrücken konnte, zum Beispiel mit einer Schleife, mit einzelnen Schritten in einzelnen Funktionsaufrufen lösen. Dabei muss man sich oft Zustand über Aufrufe hinweg merken – dafür sind Klassen da. Du bist im Grunde noch dabei/davor Funktionen zu lernen, denn in dem ganzen Programm gibt es keine Funktion die den Namen verdient hätte. Stattdessen hast Du Klassen übersprungen, und gleich mit der GUI losgelegt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten