Hallo,
wie kann man es schaffen, dass man mit tkinter eine Nutzereingabe überprüft?
Zum genauen Problem: Ich bin noch ziemlicher Anfänger in Sachen programmierung und habe ein Programm (in der Kommandozeile) entwickelt, dass dem Nutzer per Zufallszahlen Rechenaufgaben erstellt, die dann gelöst werden sollen. Auf der Kommandozeile ist das kein Problem: mit der input-Anweisung frage ich nach einer Eingabe. Ist die Aufgabe richtig, dann läuft die Schleife weiter und gibt die nächste Aufgabe aus.
Aber bei tkinter komme ich an meine Grenzen: Wie mache ich klar, dass beim Klick auf eine Button die Nutzereingabe aus einer Textbox verarbeitet wird und vor allem die Schleife dann weiterläuft und die nächste Aufgabe ausgibt?
Vielen Dank für eure Ideen.
Ergebnisse auswerten und Schleife weiterlaufen lassen
- __blackjack__
- User
- Beiträge: 14084
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Cortez: Das funktioniert in GUIs komplett anders. Da hat die GUI-Hauptschleife die Kontrolle und nicht eine Schleife die Du programmiert hast. GUIs funktionieren ereignisbasiert. Du erstellst die GUI und registrierst Rückruffunktionen/-Methoden die bei bestimmten Ereignissen aufgerufen werden, und dann kurz etwas machen. Da man sich in jedem nicht-trivialen GUI-Programm Zustand über aufrufe hinweg merken muss, braucht man für GUIs objektorientierte Programmierung (OOP), muss also also eigene Klasse(n) schreiben.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Ok, das ist mir schon klar. Aber was müsste ich da umbauen. Also, ich möchte ja, dass bei einem auf den Button die Ergebniskontrolroutine aufgerufen wird. Soweit würde ich es wohl auch hinbekommen.
Es hängt bei mir nur, dass dann halt die Schleife nicht mehr weiterläuft.
Mit objektorientierter Programmierung habe ich auch das Programm auf der Kommandozeile erstellt.
Es hängt bei mir nur, dass dann halt die Schleife nicht mehr weiterläuft.
Mit objektorientierter Programmierung habe ich auch das Programm auf der Kommandozeile erstellt.
Mit Schleifen hat das erstmal nichts zu tun. Es geht einzig und alleine um die Zeit, die ein Stück Code braucht. Wenn da eine Schleife drin ist, aber er nur Sekundenbruchteile braucht, dann passt das schon. Und auch ganz ohne Schleife kann zb das abfragen eines externen Services Sekunden oder gar minutenlang blockieren, und ist dann ganz ohne Schleife auch ein Problem.
Hier im Forum wird diese Frage auch permanent diskutiert. Stichworte sind Timer, in tkinter mit “after” zu bekommen, Threads und Queues. Einfach mal ein bisschen stöbern.
Hier im Forum wird diese Frage auch permanent diskutiert. Stichworte sind Timer, in tkinter mit “after” zu bekommen, Threads und Queues. Einfach mal ein bisschen stöbern.
Code: Alles auswählen
import random
import math
import time
import sys
class Spiel:
def __init__(self, anzahl,typ):
self.anzahl = anzahl
self.typ = typ
self.korrekte_Aufgaben = 0
self.falsche_Aufgaben = 0
self.name = input ("Dein Name?")
if self.typ == 1:
self.leichte_aufgabe(anzahl)
elif self.typ == 2:
self.schwere_aufgabe(anzahl)
elif self.typ == 3:
self.speedrechnen(hs)
else:
hs.lesen()
def speedrechnen(self,hs):
startzeit,zielzeit = self.hole_zeit()
z = 0
while startzeit < zielzeit:
#print (startzeit)
y=self.leichte_aufgabe(1)
startzeit = int(round(time.time(),0))
#time.sleep(1)
if y == True:
z+=1
print ("Startzeit: ",startzeit)
print ("Zielzeit: ",zielzeit)
print ("Sie haben innerhalb ", zielzeit - startzeit," ",z," Aufgaben gelöst")
hs.dateieintrag(self.name,z)
def hole_zeit(self):
startzeit = int(round(time.time(),0))
zielzeit = startzeit +10
return startzeit,zielzeit
def leichte_aufgabe(self,anzahl):
for j in range(0, anzahl):
br1 = bruch()
br1.ausgabe()
br1.kuerze_bruch()
z = self.eingaberoutine(br1)
print (z)
self.statistik(z,anzahl)
if (z == 1 and anzahl == 1) or j == anzahl:
return True
def schwere_aufgabe(self, anzahl):
for j in range(0,anzahl):
vorz = self.vorzeichen()
br1 = bruch()
br2 = bruch()
if vorz == "+":
print (br1, " + ",br2)
erg_z,erg_n=br1.addiere(br2)
elif vorz == "-":
print (br1, " - ", br2)
erg_z,erg_n=br1.subtrahiere(br2)
elif vorz == "*":
print (br1, " * ", br2)
erg_z,erg_n=br1.multipliziere(br2)
else:
print (br1, " / ", br2)
erg_z,erg_n=br1.dividiere(br2)
br1 = bruch(erg_z,erg_n)
br1.kuerze_bruch()
br1.ausgabe()
z = self.eingaberoutine(br1)
self.statistik(z, anzahl)
def eingaberoutine(self,br1):
erg_z = 0
erg_n = 0
for i in range(1,4):
erg_z = input ("Zaehler?")
erg_n = input ("Nenner?")
erg_z = int (erg_z)
erg_n = int(erg_n)
if erg_z == br1.zehler and erg_n == br1.nenner:
print ("richtig. Sie brauchten Versuche: ", i)
return i
elif (erg_z != br1.zehler or erg_n != br1.nenner) and i == 3:
print ("Zu viele Versuche, nämlich ",i,)
return i
else:
print ("falsch")
def statistik(self, z, anzahl):
if z == 1:
self.korrekte_Aufgaben += 1
elif z == 2:
self.falsche_Aufgaben += 1
else:
self.falsche_Aufgaben += 1
if self.korrekte_Aufgaben + self.falsche_Aufgaben == anzahl:
quote = round(self.korrekte_Aufgaben/anzahl*100,2)
print ("Sie haben ", self.korrekte_Aufgaben, " von ", anzahl, " Aufgaben richtig geloest, also ", quote, " %")
def vorzeichen(self):
random.seed()
vorz=random.randint(1,4)
if vorz == 1:
return "+"
elif vorz == 2:
return "-"
elif vorz == 3:
return "*"
else:
return "/"
class bruch:
def __init__(self,zehler=0,nenner=0):
self.zehler=zehler
self.nenner=nenner
if zehler==0 or nenner ==0:
wert_zehler = self.generiere_bruchzahl()
wert_nenner = self.generiere_bruchzahl()
self.zehler += wert_zehler
self.nenner += wert_nenner
def __str__(self):
return str(self.zehler) + "/" + str(self.nenner)
def generiere_bruchzahl(self):
prob = 2,2,2,2,3,3,3,5,5,7
wert = 1
random.seed()
anz = random.randint(2,5)
for i in range(1,anz):
wert *=random.choice(prob)
return wert
def kuerze_bruch(self):
ggt = math.gcd(self.zehler,self.nenner)
self.zehler = self.zehler / ggt
self.nenner = self.nenner / ggt
self.zehler = int(self.zehler)
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.zehler *= counter
other.zehler *= 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.zehler + other.zehler
nenner = self.nenner
return ergebnis,nenner
def subtrahiere(self, other):
if self.nenner != other.nenner:
self, other = self.mache_nennergleich(other)
ergebnis = self.zehler -other.zehler
nenner = self.nenner
return ergebnis,nenner
def multipliziere(self, other):
self.kuerze_bruch()
other.kuerze_bruch()
erg_z = self.zehler*other.zehler
erg_n = self.nenner*other.nenner
return erg_z, erg_n
def dividiere(self,other):
self.kuerze_bruch()
other.kuerze_bruch()
erg_z = self.zehler*other.nenner
erg_n = self.nenner*other.zehler
return erg_z, erg_n
def ausgabe(self):
print (self.zehler, " / ", self.nenner)
class Highscore():
#def __init__(self):
def dateieintrag(self, name, z):
lt = time.localtime()
try:
datei = open("rekorde.txt","a")
except:
print ("Konnte Datei nicht oeffnen")
datei.write(name+" hat am " +time.strftime("%d.%m.%Y",lt) + " "+str(z)+" Aufgaben richtig" + "\n")
datei.close()
try:
datei2 = open("daten.csv","a")
except:
print ("Konnte Datei nicht oeffnen")
datei2.write(name + ";" + str(z) + "\n")
datei2.close()
def lesen(self):
try:
datei = open("rekorde.txt")
except:
print ("Dateizugriff nicht erfolgreich")
allezeilen = datei.readlines()
datei.close()
such = " "
print (f"{'Name':>11}{'Aufgaben':>30}")
for zeile in allezeilen:
anzahl = zeile.count(such)
pos = zeile.find(such)
anfpos = pos
#print (anzahl, " ", pos)
for i in range(1,5):
#print (zeile)
pos = zeile.find(such, pos+1)
#print (pos)
#print (zeile[0:anfpos], " ",zeile[pos-1], " Aufgaben")
name = zeile[0:anfpos]
zahl = zeile[pos-1]
print (f"{zeile[0:anfpos]:>10}{int(zeile[pos-1]):20.0f}")
try:
datei2 = open("daten.csv")
except:
print ("Dateizugriff nicht erfolgreich")
gesamt = datei2.read()
datei2.close()
zeilen=gesamt.split(chr(10))
li = []
for zeile in zeilen:
zwliste = zeile.split(";")
print (zwliste)
li.append(zwliste)
print (li)
li2 = []
for s in range(0,len(li)):
sort = sorted(li[s])
li2.append(sort)
print (li2)
li = sorted(li2)
print (li)
for p in range(len(li)-1,0,-1):
print(f"{li[p][1]:<20}{int(li[p][0]):>2}")
print ("Hauptprogramm")
hs = Highscore()
anzahl = input ("Wieviel Aufgaben?")
typ = input ("Aufgabentyp?")
anzahl = int(anzahl)
typ = int(typ)
s = Spiel(anzahl,typ)
Zur Erklärung: Es ist ein Programm zum Bruchrechnen. Man kann verschiedene Modi wählen:
1: ausgegebener Bruch muss vollständig gekürzt werden.
2: Bruchrechenaufgabe: Addition/Subtraktion/Multiplikation/Division
3: Speedrechnen: Der Spieler hat 10 Sekunden um möglichst viele Brüche vollständig zu kürzen. Sein ergebnis wird in einer highscore-Datei gespeichert.
Die Highscore-Datei kann man sich auch ausgeben lassen.
Eines vorweg: Ich weiß, dass eine Fehler/Ausnahmebehandlung noch nicht stattgefunden hat.
Das Programm ist objektorientiert geschrieben, also es gibt das Objekt "spiel" und das Objekt "Bruch"
Und als nächsten Schritt wollte ich das Ganze, Stück für Stück, auf einem GUI zum Laufen bringen.
Schonmal danke dafür, dass ihr geantwortet habt. Ich hoffe nur, mein Code ist nicht zu stümperhaft (ist mein erster Versuch nach Ewigkeiten

Da haben wir ja schon das Problem: die Klasse ›Spiel‹ ist gar keine richtige Klasse. __init__ ist dazu da eine Klasse zu initialisieren, nicht dass darin alles läuft. leichte_aufgabe oder schwere_aufgabe muß außerhalb aufgerufen werden.
Zudem ist `hs` eine globale Variable, solche Fehler würden gar nicht auftreten, wenn Du eine main-Funktion hättest.
Und jetzt sollte es einfach sein, die Schleife in ›leichte_aufgabe‹ so aufzuteilen, dass die Einzelteile durch Knopfdrücke ausgeführt werden.
Sonstige Anmerkungen:
Variablennamen und Attribute werden komplett klein geschrieben. Benutze keine Abkürzungen. Warum br1 in leichte_aufgaben wenn es nur einen Bruch gibt?
`hole_zeit`, `eingaberoutine` und `vorzeichen` gehören gar nicht in die Klasse, weil sie `self` gar nicht brauchen.
In `vorzeichen` ist random.seed falsch, weil es die Zufälligkeit stört. Statt randint und den ifs wäre ein random.choice einfacher.
`bruch` ist falsch geschrieben, weil Klassen groß geschrieben werden: Bruch. Zähler schreibt man nicht mit e.
`bruch.__str__`: statt Strings mit + zusammenzustückeln benutzt man Formatstrings.
`generiere_bruchzahl` generiert gar keine Bruchzahl und benutzt self nicht.
In `kuerze_bruch` benutzt Ganzzahldivision //.
`mache_nennergleich` ändert self und other und gibt zwei Brüche zurück. Eine Funktion sollte nicht unkommentiert Argumente verändern.
`addiere`, `subtrahiere`, `multipliziere` und `dividiere` sollten einen Bruch zurückliefern und die übergebenen Brüche nicht verändern.
`ausgabe` ist überflüssig da es ja bruch.__str__ gibt.
In `Highscore` sollte man keine nackten excepts benutzen, vor allem weil die Fehlerbehandlung kaputt ist, da sie das Programm nicht in einen funktionierenden Zustand versetzt.
Dateien öffnet man mit dem with-Statement.
Zudem ist `hs` eine globale Variable, solche Fehler würden gar nicht auftreten, wenn Du eine main-Funktion hättest.
Code: Alles auswählen
class Spiel:
def __init__(self):
self.korrekte_aufgaben = 0
self.falsche_aufgaben = 0
self.name = input ("Dein Name?")
...
def main():
print("Hauptprogramm")
anzahl = int(input("Wieviel Aufgaben?"))
typ = int(input("Aufgabentyp?"))
spiel = Spiel()
if typ == 1:
spiel.leichte_aufgabe(anzahl)
elif self.typ == 2:
spiel.schwere_aufgabe(anzahl)
elif self.typ == 3:
hs = Highscore()
spiel.speedrechnen(hs)
if __name__ == '__main__':
main()
Sonstige Anmerkungen:
Variablennamen und Attribute werden komplett klein geschrieben. Benutze keine Abkürzungen. Warum br1 in leichte_aufgaben wenn es nur einen Bruch gibt?
`hole_zeit`, `eingaberoutine` und `vorzeichen` gehören gar nicht in die Klasse, weil sie `self` gar nicht brauchen.
In `vorzeichen` ist random.seed falsch, weil es die Zufälligkeit stört. Statt randint und den ifs wäre ein random.choice einfacher.
Code: Alles auswählen
def vorzeichen():
return random.choice("+-*/")
`bruch.__str__`: statt Strings mit + zusammenzustückeln benutzt man Formatstrings.
`generiere_bruchzahl` generiert gar keine Bruchzahl und benutzt self nicht.
In `kuerze_bruch` benutzt Ganzzahldivision //.
`mache_nennergleich` ändert self und other und gibt zwei Brüche zurück. Eine Funktion sollte nicht unkommentiert Argumente verändern.
`addiere`, `subtrahiere`, `multipliziere` und `dividiere` sollten einen Bruch zurückliefern und die übergebenen Brüche nicht verändern.
`ausgabe` ist überflüssig da es ja bruch.__str__ gibt.
In `Highscore` sollte man keine nackten excepts benutzen, vor allem weil die Fehlerbehandlung kaputt ist, da sie das Programm nicht in einen funktionierenden Zustand versetzt.
Dateien öffnet man mit dem with-Statement.
Ok, vielen Dank für deine ausführliche Antwort.
Ok, das mit der __init -funktion macht Sinn. Wenn das im Hauptprogramm wäre, dann wären wir der Sache schon näher.
Zugegebenermaßen sind nicht alle Variablen und funktionennamen von mir gut gewählt.
Ok, hole_zeit usw. kommt auch ins Hauptprogramm.
mache_nennergleich habe ich auch so gedacht, dass er zwei Brüche zurückgibt. Beide Brüche verändern sich ja in der Regel dadurch...
Ausgabe ist überflüssig - hast Recht.
hs habe ich global gemacht, dass man von überall drauf zugreifen kann.
Wie gesagt, die Fehlerbehandlung ist noch nicht vorhanden.
Datei öffnen haben ich nach meinem Lehrbuch nachprogrammiert. Von einem with-statement war da leider nie die Rede.
Schon mal Danke bis hierher für deine Mühe.
Ok, das mit der __init -funktion macht Sinn. Wenn das im Hauptprogramm wäre, dann wären wir der Sache schon näher.
Zugegebenermaßen sind nicht alle Variablen und funktionennamen von mir gut gewählt.
Ok, hole_zeit usw. kommt auch ins Hauptprogramm.
mache_nennergleich habe ich auch so gedacht, dass er zwei Brüche zurückgibt. Beide Brüche verändern sich ja in der Regel dadurch...
Ausgabe ist überflüssig - hast Recht.
hs habe ich global gemacht, dass man von überall drauf zugreifen kann.
Wie gesagt, die Fehlerbehandlung ist noch nicht vorhanden.
Datei öffnen haben ich nach meinem Lehrbuch nachprogrammiert. Von einem with-statement war da leider nie die Rede.
Schon mal Danke bis hierher für deine Mühe.
So, habe den Code mal ein wenig verbessert.
Code: Alles auswählen
import random
import math
import time
import sys
def vorzeichenwahl():
return random.choice("+-*/")
def eingaberoutine(bruch):
ergebnis_zaehler = 0
ergebnis_nenner = 0
for i in range(1,4):
ergebnis_zaehler = input ("Zaehler?")
ergebnis_nenner = input ("Nenner?")
ergebnis_zaehler = int (ergebnis_zaehler)
ergebnis_nenner = int(ergebnis_nenner)
if ergebnis_zaehler == bruch.zähler and ergebnis_nenner == bruch.nenner:
print ("richtig. Sie brauchten der Versuche ", i)
return i
elif (ergebnis_zaehler != bruch.zähler or ergebnis_nenner != bruch.nenner) and i == 3:
print ("Zu viele Versuche, nämlich ",i,)
return i
else:
print ("falsch")
def hole_zeit():
startzeit = int(round(time.time(),0))
zielzeit = startzeit +10
return startzeit,zielzeit
class Spiel:
def __init__(self):
#self.anzahl = anzahl
#self.typ = typ
self.korrekte_Aufgaben = 0
self.falsche_Aufgaben = 0
self.name = input ("Dein Name?")
def speedrechnen(self,hs):
startzeit,zielzeit = hole_zeit()
z = 0
while startzeit < zielzeit:
#print (startzeit)
y=self.leichte_aufgabe(1)
startzeit = int(round(time.time(),0))
#time.sleep(1)
if y == True:
z+=1
print ("Startzeit: ",startzeit)
print ("Zielzeit: ",zielzeit)
print ("Sie haben innerhalb ", zielzeit - startzeit," ",z," Aufgaben gelöst")
hs.dateieintrag(self.name,z)
def leichte_aufgabe(self,anzahl):
for j in range(0, anzahl):
bruch = Bruch()
bruch.ausgabe()
bruch.kuerze_bruch()
bruch.ausgabe()
z = eingaberoutine(bruch)
print (z)
self.statistik(z,anzahl)
if (z == 1 and anzahl == 1) or j == anzahl:
return True
def schwere_aufgabe(self, anzahl):
for j in range(0,anzahl):
vorzeichen = vorzeichenwahl()
bruch1 = Bruch()
bruch2 = Bruch()
if vorzeichen == "+":
print (bruch1, " + ",bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.addiere(bruch2)
elif vorzeichen == "-":
print (bruch1, " - ", bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.subtrahiere(bruch2)
elif vorzeichen == "*":
print (bruch1, " * ", bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.multipliziere(bruch2)
else:
print (bruch1, " / ", bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.dividiere(bruch2)
bruch = Bruch(ergebnis_zaehler,ergebnis_nenner)
bruch.kuerze_bruch()
bruch.ausgabe()
z = eingaberoutine(bruch)
self.statistik(z, anzahl)
def statistik(self, z, anzahl):
if z == 1:
self.korrekte_Aufgaben += 1
elif z == 2:
self.falsche_Aufgaben += 1
else:
self.falsche_Aufgaben += 1
if self.korrekte_Aufgaben + self.falsche_Aufgaben == anzahl:
quote = round(self.korrekte_Aufgaben/anzahl*100,2)
print ("Sie haben ", self.korrekte_Aufgaben, " von ", anzahl, " Aufgaben richtig geloest, also ", quote, " %")
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)
class Highscore():
#def __init__(self):
def dateieintrag(self, name, z):
lt = time.localtime()
try:
datei = open("rekorde.txt","a")
except:
print ("Konnte Datei nicht oeffnen")
datei.write(name+" hat am " +time.strftime("%d.%m.%Y",lt) + " "+str(z)+" Aufgaben richtig" + "\n")
datei.close()
try:
datei2 = open("daten.csv","a")
except:
print ("Konnte Datei nicht oeffnen")
datei2.write(name + ";" + str(z) + "\n")
datei2.close()
def lesen(self):
try:
datei = open("rekorde.txt")
except:
print ("Dateizugriff nicht erfolgreich")
allezeilen = datei.readlines()
datei.close()
such = " "
print (f"{'Name':>11}{'Aufgaben':>30}")
for zeile in allezeilen:
anzahl = zeile.count(such)
pos = zeile.find(such)
anfpos = pos
#print (anzahl, " ", pos)
for i in range(1,5):
#print (zeile)
pos = zeile.find(such, pos+1)
#print (pos)
#print (zeile[0:anfpos], " ",zeile[pos-1], " Aufgaben")
name = zeile[0:anfpos]
zahl = zeile[pos-1]
print (f"{zeile[0:anfpos]:>10}{int(zeile[pos-1]):20.0f}")
try:
datei2 = open("daten.csv")
except:
print ("Dateizugriff nicht erfolgreich")
gesamt = datei2.read()
datei2.close()
zeilen=gesamt.split(chr(10))
li = []
for zeile in zeilen:
zwliste = zeile.split(";")
print (zwliste)
li.append(zwliste)
print (li)
li2 = []
for s in range(0,len(li)):
sort = sorted(li[s])
li2.append(sort)
print (li2)
li = sorted(li2)
print (li)
for p in range(len(li)-1,0,-1):
print(f"{li[p][1]:<20}{int(li[p][0]):>2}")
def main():
print ("Hauptprogramm")
hs = Highscore()
anzahl = int(input ("Wieviel Aufgaben?"))
typ = int(input ("Aufgabentyp?"))
spiel = Spiel()
if typ == 1:
spiel.leichte_aufgabe(anzahl)
elif typ == 2:
spiel.schwere_aufgabe(anzahl)
elif typ == 3:
hs = Highscore()
spiel.speedrechnen(hs)
hs.lesen()
if __name__ == '__main__':
main()
Das oben genannte Problem habe ich aber immernoch.
Und vor allem kapiere ich nicht, wie ich die tkinter-Objekte in die Methoden meiner Klassen implementieren soll. Die werden nicht erkannt, wenn ich das Fenster mit in die main - Funktion packe. Wenn ich das Fenster allerdings ganz nach "oben" in den Code packe, kann ich über die tkinter-Objekte die Objekte meiner Klasse nicht nutzen.
Muss ich da irgendwas global machen? Oder geht das irgendwie anders?
Ich habe keinen Plan mehr, was ich noch versuchen könnte.
Und vor allem kapiere ich nicht, wie ich die tkinter-Objekte in die Methoden meiner Klassen implementieren soll. Die werden nicht erkannt, wenn ich das Fenster mit in die main - Funktion packe. Wenn ich das Fenster allerdings ganz nach "oben" in den Code packe, kann ich über die tkinter-Objekte die Objekte meiner Klasse nicht nutzen.
Muss ich da irgendwas global machen? Oder geht das irgendwie anders?
Ich habe keinen Plan mehr, was ich noch versuchen könnte.
Das offensichtliche ist ja, alle Ein- und Ausgaben durch GUI-Elemente zu ersetzen.
Also aus
müssen drei Teile werden:
1. einen neuen Bruch erzeugen und diesen in der GUI anzeigen (also Labelinhalte entsprechend setzen).
2. Du brauchst Eingabefelder und einen Ok-Button und beim Druch auf Ok muß die Eingabe geprüft werden (also die Schleife in eingaberoutine kann so auch nicht bestehen bleiben).
3. Statistik: das ist ja auch nur eine Ausgabe, also das setzen von entsprechenden Labelinhalten.
Also aus
Code: Alles auswählen
bruch = Bruch()
bruch.ausgabe()
bruch.kuerze_bruch()
bruch.ausgabe()
z = eingaberoutine(bruch)
print (z)
self.statistik(z,anzahl)
1. einen neuen Bruch erzeugen und diesen in der GUI anzeigen (also Labelinhalte entsprechend setzen).
2. Du brauchst Eingabefelder und einen Ok-Button und beim Druch auf Ok muß die Eingabe geprüft werden (also die Schleife in eingaberoutine kann so auch nicht bestehen bleiben).
3. Statistik: das ist ja auch nur eine Ausgabe, also das setzen von entsprechenden Labelinhalten.
Ok, vielen Dank für den Input.
Die statistikfunktion lassen wir vielleicht erstmal beiseite und gehen Schritt für Schritt vor.
Das Hauptfenster soll 5 Buttons haben (einfache Aufgabe, schwere Aufgaben, Speedrechnen, Highscore einsehen, Ende).
Darüber hinaus den "OK" Button, von dem du sprachst.
Zur Anzeige / Eingabe der einfachen Aufgabe stehen entsprechend Labels und Entries zur Verfügung.
Namen und Anzahl der Aufgaben würde ich zu Testzwecken mal fix vorgeben. Das könnte man dann in einem weiteren Schritt per Eingabefeld regeln.
Ich codiere mal so weit und würde den Code dann später posten, wenn ich soweit bin. Dann lässt sich sicher am Besten erkennen, wo der Hund begraben liegt.
Die statistikfunktion lassen wir vielleicht erstmal beiseite und gehen Schritt für Schritt vor.
Das Hauptfenster soll 5 Buttons haben (einfache Aufgabe, schwere Aufgaben, Speedrechnen, Highscore einsehen, Ende).
Darüber hinaus den "OK" Button, von dem du sprachst.
Zur Anzeige / Eingabe der einfachen Aufgabe stehen entsprechend Labels und Entries zur Verfügung.
Namen und Anzahl der Aufgaben würde ich zu Testzwecken mal fix vorgeben. Das könnte man dann in einem weiteren Schritt per Eingabefeld regeln.
Ich codiere mal so weit und würde den Code dann später posten, wenn ich soweit bin. Dann lässt sich sicher am Besten erkennen, wo der Hund begraben liegt.
So, hier mal mein Code bis jetzt. Ich habe als Start jetzt mal so programmiert, dass beim Klick auf den entsprechenden Button einfach ein Bruch erzeugt und anschließend mit der entsprechenden Methode gekürzt wird.
Aber schon hier gibts Probleme:
Gebe ich ein bruch.kuerze_bruch() ein, erhalte ich die Fehlermedung: kuerze_bruch() missing 1 required positional argument: 'self'
Was bitte soll da übergeben werden?
Kommentiere ich diese Funktion aus, erhalte ich folgende Fehlermeldung:AttributeError: type object 'Bruch' has no attribute 'zähler'
HÄ? Selbstverständlich existiert dieses attribut, wie sich aus der Klasse unschwer ersehen lässt.
EDIT: Habe dafür den Fehler gefunden. Beim Objekterzeugen hat eine Klammer gefehlt.
Hier dennoch mal der Code:
Soweit, sogut.
Nun habe ich eine OK-Button erstellt und möchte, dass beim Klick darauf die Ergebniskontrollroutine kommt. Aber das funktioniert nicht, weil das Objekt "bruch" nicht erkannt wird. Müsste ich daher die Variable "bruch" global setzen?
Hier mal der hinzugefügte Code:
Aber schon hier gibts Probleme:
Gebe ich ein bruch.kuerze_bruch() ein, erhalte ich die Fehlermedung: kuerze_bruch() missing 1 required positional argument: 'self'
Was bitte soll da übergeben werden?
Kommentiere ich diese Funktion aus, erhalte ich folgende Fehlermeldung:AttributeError: type object 'Bruch' has no attribute 'zähler'
HÄ? Selbstverständlich existiert dieses attribut, wie sich aus der Klasse unschwer ersehen lässt.
EDIT: Habe dafür den Fehler gefunden. Beim Objekterzeugen hat eine Klammer gefehlt.
Hier dennoch mal der Code:
Code: Alles auswählen
import tkinter
import random
import math
import time
import sys
def vorzeichenwahl():
return random.choice("+-*/")
def eingaberoutine(bruch):
ergebnis_zaehler = 0
ergebnis_nenner = 0
for i in range(1,4):
ergebnis_zaehler = int(zähler_eingabe.get())
ergebnis_nenner = int(nenner_eingabe.get())
if ergebnis_zaehler == bruch.zähler and ergebnis_nenner == bruch.nenner:
print ("richtig. Sie brauchten der Versuche ", i)
return i
elif (ergebnis_zaehler != bruch.zähler or ergebnis_nenner != bruch.nenner) and i == 3:
print ("Zu viele Versuche, nämlich ",i,)
return i
else:
print ("falsch")
def hole_zeit():
startzeit = int(round(time.time(),0))
zielzeit = startzeit +10
return startzeit,zielzeit
class Spiel:
def __init__(self):
#self.anzahl = anzahl
#self.typ = typ
self.korrekte_Aufgaben = 0
self.falsche_Aufgaben = 0
#self.name = input ("Dein Name?")
self.name = "Max Mustermann"
def speedrechnen(self,hs):
startzeit,zielzeit = hole_zeit()
z = 0
while startzeit < zielzeit:
#print (startzeit)
y=self.leichte_aufgabe(1)
startzeit = int(round(time.time(),0))
#time.sleep(1)
if y == True:
z+=1
print ("Startzeit: ",startzeit)
print ("Zielzeit: ",zielzeit)
print ("Sie haben innerhalb ", zielzeit - startzeit," ",z," Aufgaben gelöst")
hs.dateieintrag(self.name,z)
def leichte_aufgabe(self,anzahl):
for j in range(0, anzahl):
bruch = Bruch()
bruch.ausgabe()
bruch.kuerze_bruch()
bruch.ausgabe()
z = eingaberoutine(bruch)
print (z)
self.statistik(z,anzahl)
if (z == 1 and anzahl == 1) or j == anzahl:
return True
def schwere_aufgabe(self, anzahl):
for j in range(0,anzahl):
vorzeichen = vorzeichenwahl()
bruch1 = Bruch()
bruch2 = Bruch()
if vorzeichen == "+":
print (bruch1, " + ",bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.addiere(bruch2)
elif vorzeichen == "-":
print (bruch1, " - ", bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.subtrahiere(bruch2)
elif vorzeichen == "*":
print (bruch1, " * ", bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.multipliziere(bruch2)
else:
print (bruch1, " / ", bruch2)
ergebnis_zaehler,ergebnis_nenner=bruch1.dividiere(bruch2)
bruch = Bruch(ergebnis_zaehler,ergebnis_nenner)
bruch.kuerze_bruch()
bruch.ausgabe()
z = eingaberoutine(bruch)
self.statistik(z, anzahl)
def statistik(self, z, anzahl):
if z == 1:
self.korrekte_Aufgaben += 1
elif z == 2:
self.falsche_Aufgaben += 1
else:
self.falsche_Aufgaben += 1
if self.korrekte_Aufgaben + self.falsche_Aufgaben == anzahl:
quote = round(self.korrekte_Aufgaben/anzahl*100,2)
print ("Sie haben ", self.korrekte_Aufgaben, " von ", anzahl, " Aufgaben richtig geloest, also ", quote, " %")
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)
class Highscore():
#def __init__(self):
def dateieintrag(self, name, z):
lt = time.localtime()
try:
datei = open("rekorde.txt","a")
except:
print ("Konnte Datei nicht oeffnen")
datei.write(name+" hat am " +time.strftime("%d.%m.%Y",lt) + " "+str(z)+" Aufgaben richtig" + "\n")
datei.close()
try:
datei2 = open("daten.csv","a")
except:
print ("Konnte Datei nicht oeffnen")
datei2.write(name + ";" + str(z) + "\n")
datei2.close()
def lesen(self):
try:
datei = open("rekorde.txt")
except:
print ("Dateizugriff nicht erfolgreich")
allezeilen = datei.readlines()
datei.close()
such = " "
print (f"{'Name':>11}{'Aufgaben':>30}")
for zeile in allezeilen:
anzahl = zeile.count(such)
pos = zeile.find(such)
anfpos = pos
#print (anzahl, " ", pos)
for i in range(1,5):
#print (zeile)
pos = zeile.find(such, pos+1)
#print (pos)
#print (zeile[0:anfpos], " ",zeile[pos-1], " Aufgaben")
name = zeile[0:anfpos]
zahl = zeile[pos-1]
print (f"{zeile[0:anfpos]:>10}{int(zeile[pos-1]):20.0f}")
try:
datei2 = open("daten.csv")
except:
print ("Dateizugriff nicht erfolgreich")
gesamt = datei2.read()
datei2.close()
zeilen=gesamt.split(chr(10))
li = []
for zeile in zeilen:
zwliste = zeile.split(";")
print (zwliste)
li.append(zwliste)
print (li)
li2 = []
for s in range(0,len(li)):
sort = sorted(li[s])
li2.append(sort)
print (li2)
li = sorted(li2)
print (li)
for p in range(len(li)-1,0,-1):
print(f"{li[p][1]:<20}{int(li[p][0]):>2}")
def main():
def typ1():
#spiel = Spiel()
#spiel.leichte_aufgabe(3)
bruch = Bruch()
bruch.kuerze_bruch()
zähler_anzeige["text"] = str(bruch.zähler)
nenner_anzeige["text"] = str(bruch.nenner)
def typ2():
pass
def speedrechnen():
pass
def siehe_highscore():
pass
def ende():
haupt.destroy()
haupt = tkinter.Tk()
framelinks = tkinter.Frame(haupt, width=50)
#framelinks["bg"] = "#FF0000"
framelinks.pack(side="left", pady=0)
zähler_anzeige = tkinter.Label(framelinks, text = "3")
zähler_anzeige["width"] = 2
zähler_anzeige["height"] = 0
zähler_anzeige["font"] = "Arial 70 bold"
zähler_anzeige["bg"] = "cyan"
zähler_anzeige["anchor"] = "s"
zähler_anzeige.pack(pady = 30)
bruchstrich = tkinter.Label(framelinks, text = "_____")
bruchstrich["width"] = 0
bruchstrich["height"] = 0
bruchstrich["font"] = "Arial 40 bold"
#bruchstrich["anchor"] = "n"
bruchstrich.pack(pady = 0)
nenner_anzeige = tkinter.Label(framelinks, text = "4")
nenner_anzeige["width"] = 2
nenner_anzeige["bg"] = "cyan"
nenner_anzeige["height"] = 0
nenner_anzeige["font"] = "Arial 70 bold"
nenner_anzeige.pack(pady = 50)
framemitte = tkinter.Frame(haupt, width=50)
#framemitte["bg"] = "red"
framemitte.pack(side="left",pady=0)
istgleich = tkinter.Label(framemitte, text = "=")
istgleich["font"] = "Arial 70 bold"
istgleich["height"] = 0
istgleich["bg"] = "white"
istgleich["anchor"] = "n"
istgleich.pack(padx = 20)
framebuttons = tkinter.Frame(haupt, width=50)
framebuttons.pack(side="right",pady=0)
buttonende = tkinter.Button(framebuttons, text = "Ende", command = ende)
buttonende.pack(pady=0)
buttonaufgabe1 = tkinter.Button(framebuttons, text =" Kuerzen", command = typ1)
buttonaufgabe1.pack(pady=0,side="left")
buttonaufgabe2 = tkinter.Button(framebuttons, text = "Bruchrechnen", command = typ2)
buttonaufgabe2.pack()
buttonspeed = tkinter.Button(framebuttons, text = "Speedrechnen", command = speedrechnen)
buttonspeed.pack()
buttonhighscore = tkinter.Button(framebuttons, text = "Highscore ansehen", command = siehe_highscore)
buttonhighscore.pack()
framerechts = tkinter.Frame(haupt,width=500)
framerechts.pack(side="left",pady=2)
zähler_eingabe = tkinter.Entry(framerechts)
zähler_eingabe["bg"] = "white"
zähler_eingabe["font"] = "Arial 70 bold"
zähler_eingabe["width"] = 2
#zehler_eingabe["anchor"] = "center"
zähler_eingabe.pack(padx = 20,pady = 0)
bruchstrich2 = tkinter.Label(framerechts, text = "_____")
bruchstrich2["width"] = 0
bruchstrich2["height"] = 0
bruchstrich2["font"] = "Arial 40 bold"
#bruchstrich["anchor"] = "n"
bruchstrich2.pack(pady = 30)
nenner_eingabe = tkinter.Entry(framerechts)
nenner_eingabe["bg"] = "white"
nenner_eingabe["font"] = "Arial 70 bold"
nenner_eingabe["width"] = 2
#nenner_eingabe["anchor"] = "center"
nenner_eingabe.pack(padx = 20,pady = 20)
ausgabelabel = tkinter.Label(haupt, text = "ausgabe")
ausgabelabel.pack()
print ("Hauptprogramm")
hs = Highscore()
#anzahl = int(input ("Wieviel Aufgaben?"))
#typ = int(input ("Aufgabentyp?"))
spiel = Spiel()
haupt.mainloop()
#if typ == 1:
#spiel.leichte_aufgabe(anzahl)
#elif typ == 2:
#spiel.schwere_aufgabe(anzahl)
#elif typ == 3:
#hs = Highscore()
#spiel.speedrechnen(hs)
#hs.lesen()
if __name__ == '__main__':
main()
#s = Spiel(5,1)
Nun habe ich eine OK-Button erstellt und möchte, dass beim Klick darauf die Ergebniskontrollroutine kommt. Aber das funktioniert nicht, weil das Objekt "bruch" nicht erkannt wird. Müsste ich daher die Variable "bruch" global setzen?
Hier mal der hinzugefügte Code:
buttonok = tkinter.Button(framebuttons, text = "OK", command = eingaberoutine(bruch))
- __blackjack__
- User
- Beiträge: 14084
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Cortez: ``global`` ist da gar nichts zu setzen. Grundsätzlich nicht!
`command` erwartet etwas Aufrufbares das kein Argument bekommt. Du rufst da `eingaberoutine()` auf und übergibst den *Rückgabewert* davon als `command`. Das geht nicht. Also das ginge nicht einmal wenn `bruch` definiert wäre.
Lokale Funktionen so wie in der `main()` macht man nicht. Du brauchst für die GUI eine Klasse. Und für die Programmlogik Code der keinen GUI-Code enthält. Deine `eingaberoutine()` fragt in einer Schleife immer wieder die gleichen Eingabeelemente ab — das funktioniert so nicht weil der Benutzer nie die Möglichkeit hat da andere Werte einzugeben, da werden also direkt hintereinander weg jedes mal die gleichen Werte abgefragt und verarbeitet bis die Versuche aufgebraucht sind.
GUI-Programmierung funktioniert wirklich komplett anders als der lineare Programmablauf bei einer Konsolananwendung. Ich denke nicht, dass es Sinn macht, dass Du versuchst den alten Code, der ja auch schon deutliche Probleme mit OOP hatte, jetzt irgendwie in eine GUI-Anwendung umzubauen. Die solltest Du besser von Grund auf neu schreiben. Oder zumindest mit dem Zwischenschritt die Konsolenanwendung zuerst einmal so umzuschreiben das es immer noch eine Konsolenanwendung ist, aber Programmlogik und Benutzerinteraktion komplett getrennt sind, und man ein Objekt mit der Programmlogik hat, das so gestaltet ist, dass man es sowohl von einer Konsolenanwendung als auch von einer GUI-Anwendung benutzen kann.
`command` erwartet etwas Aufrufbares das kein Argument bekommt. Du rufst da `eingaberoutine()` auf und übergibst den *Rückgabewert* davon als `command`. Das geht nicht. Also das ginge nicht einmal wenn `bruch` definiert wäre.
Lokale Funktionen so wie in der `main()` macht man nicht. Du brauchst für die GUI eine Klasse. Und für die Programmlogik Code der keinen GUI-Code enthält. Deine `eingaberoutine()` fragt in einer Schleife immer wieder die gleichen Eingabeelemente ab — das funktioniert so nicht weil der Benutzer nie die Möglichkeit hat da andere Werte einzugeben, da werden also direkt hintereinander weg jedes mal die gleichen Werte abgefragt und verarbeitet bis die Versuche aufgebraucht sind.
GUI-Programmierung funktioniert wirklich komplett anders als der lineare Programmablauf bei einer Konsolananwendung. Ich denke nicht, dass es Sinn macht, dass Du versuchst den alten Code, der ja auch schon deutliche Probleme mit OOP hatte, jetzt irgendwie in eine GUI-Anwendung umzubauen. Die solltest Du besser von Grund auf neu schreiben. Oder zumindest mit dem Zwischenschritt die Konsolenanwendung zuerst einmal so umzuschreiben das es immer noch eine Konsolenanwendung ist, aber Programmlogik und Benutzerinteraktion komplett getrennt sind, und man ein Objekt mit der Programmlogik hat, das so gestaltet ist, dass man es sowohl von einer Konsolenanwendung als auch von einer GUI-Anwendung benutzen kann.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Ok, das sehe ich ein. Mein Programm scheint für den GUI-Gebrauch nicht geeignet zu sein. Also für diesen Zweck neumachen.
Das Problem, das ich dabei habe ist nur Folgendes: Wie kann man eigene Klassen (wie bei mir z.B. Bruch) in die GUI-Programmierung miteinbringen? Alles, was man so an Tutorials findet, erklärt lediglich, wie man Buttons mit Funktionen außerhalb von Klassen verknüpft-
Aber ich müsste ja mit einem Buttondruck Methoden der Klasse aufrufen. Und Übergabewerte (die Nutzereingaben) brauche ich ja auch...
Das Problem, das ich dabei habe ist nur Folgendes: Wie kann man eigene Klassen (wie bei mir z.B. Bruch) in die GUI-Programmierung miteinbringen? Alles, was man so an Tutorials findet, erklärt lediglich, wie man Buttons mit Funktionen außerhalb von Klassen verknüpft-
Aber ich müsste ja mit einem Buttondruck Methoden der Klasse aufrufen. Und Übergabewerte (die Nutzereingaben) brauche ich ja auch...