Ergebnisse auswerten und Schleife weiterlaufen lassen

Fragen zu Tkinter.
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Dafür hat man eine GUI-Klasse, die den Zustand enthält, bei Dir also ein Attribut spiel vom Typ Spiel. Aber dieses Spiel muß komplett über Methoden spielbar sein, ohne dass innerhalb der Klasse irgendwo direkt Nutzerabfragen stattfinden.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Ok, das bedeutet also, wenn ich dich recht verstanden habe, dass die GUI-Klasse sämtliche Interaktion mit dem Nutzer übernimmt. Die anderen Klassen (nenne ich einfach mal so) berechnen und verwerten usw., aber können selbst keine Nutzereingaben fordern.

Habe ich das so einigermaßen korrekt verstanden? Und ist die GUI-Klasse die mainloop-Funktion?
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

JA soweit richtig. Aber wie kann eine Klasse eine Funktion sein? Es gibt eine Funktion main, die erzeugt die GUI-Klasse und ruft zum Schluß auf der Tk-Instanz mainloop auf.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Hallo,

ich habe jetzt mal versucht, das Programm ein wenig GUI-freundlicher zu gestalten. Das Problem, das ich habe, ist nun, dass Datentypen (in meinem Fall Objekte der Klasse Bruch) sich von einer Funktion nicht in die andere übertragen lassen.

Ich hätte 2 Lösungsansätze, weiß aber nicht, ob die gut sind:

1.) In der init-Methode der Spiel-Klasse wird automatisch ein Bruch erzeugt, in dem dann auch das Ergebnis gespeichert wird.

2.) Ich lese die Ausgabe in den labels aus, erstelle daraus einen neuen Bruch und nehme diesen dann als Grundlage zur Ergebnisüberprüfung.

Ich nehme an, da gibts sicherlich bessere Möglichkeiten. Hier mal der Code bis hierher:

Code: Alles auswählen

import tkinter
import random
import sys
import os
import math

class Spiel:
    
    #Spiel spielen
    
    def __init__(self):
        # das Hauptfenster
        self.hauptfenster = tkinter.Tk()
        
        
    # definiere Darstellung des zu kürzenden Bruches
        self.framelinks = tkinter.Frame(self.hauptfenster, width = 50)
        self.framelinks.pack(side = "left", pady = 0)
        
        self.zähler_anzeige = tkinter.Label(self.framelinks, text = "3")
        self.zähler_anzeige["width"] = 2
        self.zähler_anzeige["height"] = 0
        self.zähler_anzeige["font"] = "Arial 70 bold"
        self.zähler_anzeige["bg"] = "cyan"
        self.zähler_anzeige["anchor"] = "s"
        self.zähler_anzeige.pack(pady = 30)
        
        self.bruchstrich = tkinter.Label(self.framelinks, text = "_____")
        self.bruchstrich["width"] = 0
        self.bruchstrich["height"] = 0
        self.bruchstrich["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich.pack(pady = 0)
        
        self.nenner_anzeige = tkinter.Label(self.framelinks, text = "4")
        self.nenner_anzeige["width"] = 2
        self.nenner_anzeige["bg"] = "cyan"
        self.nenner_anzeige["height"] = 0
        self.nenner_anzeige["font"] = "Arial 70 bold"
        self.nenner_anzeige.pack(pady = 50)
        
        self.framemitte = tkinter.Frame(self.hauptfenster, width=50)
        #framemitte["bg"] = "red"
        self.framemitte.pack(side="left",pady=0)

        self.istgleich = tkinter.Label(self.framemitte, text = "=")
        self.istgleich["font"] = "Arial 70 bold"
        self.istgleich["height"] = 0
        self.istgleich["bg"] = "white"
        self.istgleich["anchor"] = "n"
        self.istgleich.pack(padx = 20)
        
        self.framerechts = tkinter.Frame(self.hauptfenster,width=500)
        self.framerechts.pack(side="left",pady=2)
        
        # Definition Ergebniseingabe
        
        self.zähler_eingabe = tkinter.Entry(self.framerechts)
        self.zähler_eingabe["bg"] = "white"
        self.zähler_eingabe["font"] = "Arial 70 bold"
        self.zähler_eingabe["width"] = 2
        #zehler_eingabe["anchor"] = "center"
        self.zähler_eingabe.pack(padx = 20,pady = 0)

        self.bruchstrich2 = tkinter.Label(self.framerechts, text = "_____")
        self.bruchstrich2["width"] = 0
        self.bruchstrich2["height"] = 0
        self.bruchstrich2["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich2.pack(pady = 30)

        self.nenner_eingabe = tkinter.Entry(self.framerechts)
        self.nenner_eingabe["bg"] = "white"
        self.nenner_eingabe["font"] = "Arial 70 bold"
        self.nenner_eingabe["width"] = 2
        #nenner_eingabe["anchor"] = "center"
        self.nenner_eingabe.pack(padx = 20,pady = 20)
        
        
        # Definition Buttons
        
        self.framebuttons = tkinter.Frame(self.hauptfenster, width=50)
        self.framebuttons.pack(side="right",pady=0)

        self.buttonende = tkinter.Button(self.framebuttons, text = "Ende", command = self.ende)
        self.buttonende.pack(pady=0)

        self.buttonaufgabe1 = tkinter.Button(self.framebuttons, text =" Kuerzen", command = self.typ1)
        self.buttonaufgabe1.pack(pady=0,side="left")
    
        self.buttonaufgabe2 = tkinter.Button(self.framebuttons, text = "Bruchrechnen", command = self.typ2)
        self.buttonaufgabe2.pack()
        
        self.buttonspeed = tkinter.Button(self.framebuttons, text = "Speedrechnen", command = self.speedrechnen)
        self.buttonspeed.pack()
    
        self.buttonhighscore = tkinter.Button(self.framebuttons, text = "Highscore ansehen", command = self.siehe_highscore)
        self.buttonhighscore.pack()
    
        self.buttonok = tkinter.Button(self.framebuttons, text = "OK", command = self.ergebnisroutine)
        self.buttonok.pack()
        
        # Ausgabelabel
        self.infoausgabe = tkinter.Label(self.hauptfenster, text = " ", bg = "yellow", width = 50)
        self.infoausgabe.pack()
        
        # Anzeige des Hauptfensters
        self.hauptfenster.mainloop()
        
    def typ1(self):
        bruch = Bruch()
        self.zähler_anzeige["text"] = str(bruch.zähler)
        self.nenner_anzeige["text"] = str(bruch.nenner)
        bruch.kuerze_bruch()
        print (bruch)
        
        
    def typ2(self):
        pass
    
    def speedrechnen(self):
        pass
    
    def siehe_highscore(self):
        pass
        
    def ende(self):
        self.hauptfenster.destroy()
        
    def ergebnisroutine(self,bruch):
        print (bruch)
        
class Bruch:
    def __init__(self,zähler=0,nenner=0):
        self.zähler=zähler
        self.nenner=nenner
        if zähler==0 or nenner ==0:
            wert_zähler = self.generiere_bruchzahl()
            wert_nenner = self.generiere_bruchzahl()
            self.zähler += wert_zähler
            self.nenner += wert_nenner
        
        prob = 2,2,2,2,3,3,3,5,5,7
        
    def __str__(self):
        return str(self.zähler) + "/" + str(self.nenner)
    
    def generiere_bruchzahl(self):
        prob = 2,2,2,2,3,3,3,5,5,7
        wert = 1
        #random.choice(prob)
        random.seed()
        anz = random.randint(2,5)
    
        for i in range(1,anz):
            wert *=random.choice(prob)
        #print (wert)
        
        return wert
    
    def kuerze_bruch(self):
        ggt = math.gcd(self.zähler,self.nenner)
        self.zähler = self.zähler // ggt
        self.nenner = self.nenner // ggt
        self.zähler = int(self.zähler)
        self.nenner = int(self.nenner)
        
    def mache_nennergleich(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        print (self)
        print (other)
        
        
        counter=1
        counter_b=1
    
        while self.nenner != other.nenner:
        
            if self.nenner < other.nenner:
                self.nenner += (self.nenner / counter)
                #print ("Nenner_a ", self.nenner)
                counter +=1
            
            if other.nenner < self.nenner:
                other.nenner += (other.nenner / counter_b)
                #print ("Nenner_b ", other.nenner)
                counter_b +=1
        
            if self.nenner == other.nenner:
                break
            
        self.zähler *= counter
        other.zähler *= counter_b
        self.nenner = int(self.nenner)
        other.nenner = int(other.nenner)
        return self, other
        
    def addiere(self,other):
        if self.nenner != other.nenner:
            self,other=self.mache_nennergleich(other)
        
        ergebnis = self.zähler + other.zähler
        nenner = self.nenner
        return ergebnis,nenner
        
    def subtrahiere(self, other):
        if self.nenner != other.nenner:
            self, other = self.mache_nennergleich(other)
    
        ergebnis = self.zähler -other.zähler
        nenner = self.nenner
        return ergebnis,nenner
    
    def multipliziere(self, other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.zähler
        erg_n = self.nenner*other.nenner
        return erg_z, erg_n
    
    def dividiere(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.nenner
        erg_n = self.nenner*other.zähler
        return erg_z, erg_n
            
    def ausgabe(self):
        print (self.zähler, " / ", self.nenner)
        
        

#Hauptprogramm
#if __name__ == '__main':
spiel = Spiel()
        
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Klasse Bruch hat immer noch die selben Fehler, die ich schon zu anfang angemerkt hatte.
Und wie schon geschrieben, ist __init__ zum Initialisieren da, nicht dass darin das ganze Programm läuft. Das mainloop hat darin nichts verloren.
Die ganzen Konfigurationen der Labels gibt man schon beim Erzeugen an.
Und warum ist das if-__main__ auskommentiert? Da fehlt auch noch die main-Funktion.
os und sys werden importiert, aber gar nicht benutzt.

Code: Alles auswählen

import tkinter
import random
import math

class Spiel:
    def __init__(self):
        # das Hauptfenster
        self.hauptfenster = tkinter.Tk()

        self.framelinks = tkinter.Frame(self.hauptfenster, width=50)
        self.framelinks.pack(side=tkinter.LEFT, pady=0)
        
        self.zähler_anzeige = tkinter.Label(self.framelinks,
            text="3", width=2, height=0, font="Arial 70 bold",
            bg="cyan", anchor="s")
        self.zähler_anzeige.pack(pady=30)
        
        self.bruchstrich = tkinter.Label(self.framelinks,
            text="_____", width=0, height=0, font="Arial 40 bold")
        self.bruchstrich.pack(pady=0)
        
        self.nenner_anzeige = tkinter.Label(self.framelinks,
            text="4", width=2, height=0, font="Arial 70 bold")
        self.nenner_anzeige.pack(pady=50)
        
        self.framemitte = tkinter.Frame(self.hauptfenster, width=50)
        self.framemitte.pack(side=tkinter.LEFT, pady=0)

        self.istgleich = tkinter.Label(self.framemitte,
            text="=", height=0, font="Arial 70 bold", bg="white",
            anchor=tkinter.N)
        self.istgleich.pack(padx=20)
        
        self.framerechts = tkinter.Frame(self.hauptfenster, width=500)
        self.framerechts.pack(side=tkinter.LEFT, pady=2)
        
        # Definition Ergebniseingabe
        self.zähler_eingabe = tkinter.Entry(self.framerechts,
            bg="white", font="Arial 70 bold",width=2)
        self.zähler_eingabe.pack(padx=20,pady=0)

        self.bruchstrich2 = tkinter.Label(self.framerechts,
            text="_____", width=0, height=0, font="Arial  40 bold")
        self.bruchstrich2.pack(pady=30)

        self.nenner_eingabe=tkinter.Entry(self.framerechts,
            bg="white", font="Arial 70 bold",width=2)
        self.nenner_eingabe.pack(padx = 20,pady = 20)
        
        
        # Definition Buttons
        self.framebuttons = tkinter.Frame(self.hauptfenster, width=50)
        self.framebuttons.pack(side="right",pady=0)

        self.buttonende = tkinter.Button(self.framebuttons, text = "Ende", command = self.ende)
        self.buttonende.pack(pady=0)

        self.buttonaufgabe1 = tkinter.Button(self.framebuttons, text =" Kuerzen", command = self.typ1)
        self.buttonaufgabe1.pack(pady=0,side="left")
    
        self.buttonaufgabe2 = tkinter.Button(self.framebuttons, text = "Bruchrechnen", command = self.typ2)
        self.buttonaufgabe2.pack()
        
        self.buttonspeed = tkinter.Button(self.framebuttons, text = "Speedrechnen", command = self.speedrechnen)
        self.buttonspeed.pack()
    
        self.buttonhighscore = tkinter.Button(self.framebuttons, text = "Highscore ansehen", command = self.siehe_highscore)
        self.buttonhighscore.pack()
    
        self.buttonok = tkinter.Button(self.framebuttons, text = "OK", command = self.ergebnisroutine)
        self.buttonok.pack()
        
        # Ausgabelabel
        self.infoausgabe = tkinter.Label(self.hauptfenster, text = " ", bg = "yellow", width = 50)
        self.infoausgabe.pack()
        
    ...

        

def main():
    spiel = Spiel()
    spiel.hauptfenster.mainloop()

#Hauptprogramm
if __name__ == '__main__':
    main()
Und weder 1 noch 2, denn es gibt Attribute, denen kann man auch neue Werte zuweisen.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Ok, sehe ich soweit ein. An der Klasse Bruch arbeite ich nach und nach.

Den Fehler habe ich erstmal gefunden. Habe das "self" vergessen - dann kanns mit den Attributen logischerweise nicht klappen.

Das mit der main- Funktion kann ich leider nicht nach deinem Vorschlag machen - dann bekomme ich aus irgendeinem Grund nichts mehr angezeigt. (wenn ich die auskommentierte Zeile nutze).

Nicht mal eine Fehlermeldung. Programm startet, aber ohne irgendeine Anzeige.
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Schau Dir genau die Schreibweise an.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

So, bin heute wieder mal ein bisschen zum Programmieren gekommen.

Ich habs jetzt soweit hinbekommen, dass ein Bruch erzeugt wird und das Ergebnis (der gekürzte Bruch) wird dann überprüft.

Wenn ich mehrere Aufgaben hintereinander möchte, habe ich jetzt eine neue Funktion eingebaut: Sie überprüft, ob die Anzahl der Aufgaben erreicht ist und leitet nur dann zur Ergebnisroutine weiter, wenn dies nicht der Fall ist.
Leider scheitert es daran, dass ich aus dieser Kontrollfunktion die Ergebnisroutine nicht aufrufen kann. Er meint, dass self nicht definiert sei ...

Weiß jemand Abhilfe? Hier mal der Code:

Code: Alles auswählen

import tkinter
import random
import sys
import os
import math

class Spiel:
    
    #Spiel spielen
    
    def __init__(self):
        # das Hauptfenster
        self.hauptfenster = tkinter.Tk()
        
        
    # definiere Darstellung des zu kürzenden Bruches
        self.framelinks = tkinter.Frame(self.hauptfenster, width = 50)
        self.framelinks.pack(side = "left", pady = 0)
        
        self.zähler_anzeige = tkinter.Label(self.framelinks, text = "3")
        self.zähler_anzeige["width"] = 2
        self.zähler_anzeige["height"] = 0
        self.zähler_anzeige["font"] = "Arial 70 bold"
        self.zähler_anzeige["bg"] = "cyan"
        self.zähler_anzeige["anchor"] = "s"
        self.zähler_anzeige.pack(pady = 30)
        
        self.bruchstrich = tkinter.Label(self.framelinks, text = "_____")
        self.bruchstrich["width"] = 0
        self.bruchstrich["height"] = 0
        self.bruchstrich["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich.pack(pady = 0)
        
        self.nenner_anzeige = tkinter.Label(self.framelinks, text = "4")
        self.nenner_anzeige["width"] = 2
        self.nenner_anzeige["bg"] = "cyan"
        self.nenner_anzeige["height"] = 0
        self.nenner_anzeige["font"] = "Arial 70 bold"
        self.nenner_anzeige.pack(pady = 50)
        
        self.framemitte = tkinter.Frame(self.hauptfenster, width=50)
        #framemitte["bg"] = "red"
        self.framemitte.pack(side="left",pady=0)

        self.istgleich = tkinter.Label(self.framemitte, text = "=")
        self.istgleich["font"] = "Arial 70 bold"
        self.istgleich["height"] = 0
        self.istgleich["bg"] = "white"
        self.istgleich["anchor"] = "n"
        self.istgleich.pack(padx = 20)
        
        self.framerechts = tkinter.Frame(self.hauptfenster,width=500)
        self.framerechts.pack(side="left",pady=2)
        
        # Definition Ergebniseingabe
        
        self.zähler_eingabe = tkinter.Entry(self.framerechts)
        self.zähler_eingabe["bg"] = "white"
        self.zähler_eingabe["font"] = "Arial 70 bold"
        self.zähler_eingabe["width"] = 2
        #zehler_eingabe["anchor"] = "center"
        self.zähler_eingabe.pack(padx = 20,pady = 0)

        self.bruchstrich2 = tkinter.Label(self.framerechts, text = "_____")
        self.bruchstrich2["width"] = 0
        self.bruchstrich2["height"] = 0
        self.bruchstrich2["font"] = "Arial  40 bold"
        #bruchstrich["anchor"] = "n"
        self.bruchstrich2.pack(pady = 30)

        self.nenner_eingabe = tkinter.Entry(self.framerechts)
        self.nenner_eingabe["bg"] = "white"
        self.nenner_eingabe["font"] = "Arial 70 bold"
        self.nenner_eingabe["width"] = 2
        #nenner_eingabe["anchor"] = "center"
        self.nenner_eingabe.pack(padx = 20,pady = 20)
        
        
        # Definition Buttons
        
        self.framebuttons = tkinter.Frame(self.hauptfenster, width=50)
        self.framebuttons.pack(side="right",pady=0)

        self.buttonende = tkinter.Button(self.framebuttons, text = "Ende", command = self.ende)
        self.buttonende.pack(pady=0)

        self.buttonaufgabe1 = tkinter.Button(self.framebuttons, text =" Kuerzen", command = self.typ1)
        self.buttonaufgabe1.pack(pady=0,side="left")
    
        self.buttonaufgabe2 = tkinter.Button(self.framebuttons, text = "Bruchrechnen", command = self.typ2)
        self.buttonaufgabe2.pack()
        
        self.buttonspeed = tkinter.Button(self.framebuttons, text = "Speedrechnen", command = self.speedrechnen)
        self.buttonspeed.pack()
    
        self.buttonhighscore = tkinter.Button(self.framebuttons, text = "Highscore ansehen", command = self.siehe_highscore)
        self.buttonhighscore.pack()
    
        self.buttonok = tkinter.Button(self.framebuttons, text = "OK", command = self.checkergebnis)
        self.buttonok.pack()
        
        # Ausgabelabel
        self.infoausgabe = tkinter.Label(self.hauptfenster, text = " ", bg = "yellow", width = 50)
        self.infoausgabe.pack()
        
        self.anzahl = 3
        self.aufgabenzähler = 0
        
    def typ1(self):
        self.bruch = Bruch()
        self.zähler_anzeige["text"] = str(self.bruch.zähler)
        self.nenner_anzeige["text"] = str(self.bruch.nenner)
        self.bruch.kuerze_bruch()
        print (self.bruch)
        
        
    def typ2(self):
        pass
    
    def speedrechnen(self):
        pass
    
    def siehe_highscore(self):
        pass
        
    def ende(self):
        self.hauptfenster.destroy()
        
    def checkergebnis(aufgabenzähler):
        if aufgabenzähler == 3:
            self.infoausgabe["text"] = "Alle Aufgaben gelöst"
        else:
            ergebnisroutine()
        
    def ergebnisroutine(self):
        ergebnis_zähler = 0
        ergebnis_nenner = 0
        try:
            ergebnis_zähler = int(self.zähler_eingabe.get())
            ergebnis_nenner = int(self.nenner_eingabe.get())
            #print (ergebnis_zähler)
                
        except:
            self.infoausgabe["text"] = "Bitte Zahl eingeben"
        #self.infoausgabe["text"] = str(ergebnis_zähler)
        else:
            self.infoausgabe["text"] = str(ergebnis_zähler)
            if ergebnis_zähler == self.bruch.zähler and ergebnis_nenner == self.bruch.nenner:
                self.infoausgabe["text"] = "richtig"
                self.aufgabenzähler +=1
                self.typ1()
            else:
                self.infoausgabe["text"] = "falsch"
        
class Bruch:
    def __init__(self,zähler=0,nenner=0):
        self.zähler=zähler
        self.nenner=nenner
        if zähler==0 or nenner ==0:
            wert_zähler = self.generiere_bruchzahl()
            wert_nenner = self.generiere_bruchzahl()
            self.zähler += wert_zähler
            self.nenner += wert_nenner
        
        prob = 2,2,2,2,3,3,3,5,5,7
        
    def __str__(self):
        return str(self.zähler) + "/" + str(self.nenner)
    
    def generiere_bruchzahl(self):
        prob = 2,2,2,2,3,3,3,5,5,7
        wert = 1
        #random.choice(prob)
        random.seed()
        anz = random.randint(2,5)
    
        for i in range(1,anz):
            wert *=random.choice(prob)
        #print (wert)
        
        return wert
    
    def kuerze_bruch(self):
        ggt = math.gcd(self.zähler,self.nenner)
        self.zähler = self.zähler // ggt
        self.nenner = self.nenner // ggt
        self.zähler = int(self.zähler)
        self.nenner = int(self.nenner)
        
    def mache_nennergleich(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        print (self)
        print (other)
        
        
        counter=1
        counter_b=1
    
        while self.nenner != other.nenner:
        
            if self.nenner < other.nenner:
                self.nenner += (self.nenner / counter)
                #print ("Nenner_a ", self.nenner)
                counter +=1
            
            if other.nenner < self.nenner:
                other.nenner += (other.nenner / counter_b)
                #print ("Nenner_b ", other.nenner)
                counter_b +=1
        
            if self.nenner == other.nenner:
                break
            
        self.zähler *= counter
        other.zähler *= counter_b
        self.nenner = int(self.nenner)
        other.nenner = int(other.nenner)
        return self, other
        
    def addiere(self,other):
        if self.nenner != other.nenner:
            self,other=self.mache_nennergleich(other)
        
        ergebnis = self.zähler + other.zähler
        nenner = self.nenner
        return ergebnis,nenner
        
    def subtrahiere(self, other):
        if self.nenner != other.nenner:
            self, other = self.mache_nennergleich(other)
    
        ergebnis = self.zähler -other.zähler
        nenner = self.nenner
        return ergebnis,nenner
    
    def multipliziere(self, other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.zähler
        erg_n = self.nenner*other.nenner
        return erg_z, erg_n
    
    def dividiere(self,other):
        self.kuerze_bruch()
        other.kuerze_bruch()
        
        erg_z = self.zähler*other.nenner
        erg_n = self.nenner*other.zähler
        return erg_z, erg_n
            
    def ausgabe(self):
        print (self.zähler, " / ", self.nenner)
        
        
def main():
    spiel = Spiel()
    spiel.hauptfenster.mainloop()


#Hauptprogramm
if __name__ == '__main__':
    main()
        
        
        
        
    
    
Antworten