Ozobot Oop¶
Note
11.12.24 Version 1
Aufgabe 1:¶
Erzeugen Sie einen Ozo. Der Ozo leuchtet blau und soll ein Quadrat mit 5cm Seitenlänge mit 4cm/s Geschwindigkeit fahren. Drehrichtung rechts:
Hier der Code zur Aufgabe:
import ozobot
import math
class Ozobot:
def __init__(self, geschwindigkeit, top_light_color=[1, 1, 1]):
self.ozo = ozobot.get_robot()
self.top_light_color = top_light_color
self.geschwindigkeit = geschwindigkeit / 100
self.set_top_light(top_light_color)
print("Der Ozo ist bereit!")
def set_top_light(self, color):
r = color[0]
g = color[1]
b = color[2]
self.ozo.light_effects.set_light_color_rgb(r, g, b, ozobot.Lights.TOP)
def geradeaus(self, distanz_cm):
"""Ozo fährt Distanz in cm geradeaus. Mit der Geschwindigkeit in cm/s"""
distanz_cm /= 100 # Umrechnung für move-Methode
self.ozo.movement.move(distanz_cm, self.geschwindigkeit)
print(f"Ozobot fährt {distanz_cm * 100} cm geradeaus.")
def drehen(self, richtung, grad, geschwindigkeit):
"""Dreht x Grad mit Geschwindigkeit in Grad pro Sekunde. Standardmäßig nach rechts. Mit richtung="links" nach links."""
if richtung == "links":
self.ozo.movement.rotate(math.radians(grad), math.radians(geschwindigkeit))
else:
self.ozo.movement.rotate(math.radians(-grad), math.radians(geschwindigkeit))
print(f"Ozobot dreht {grad} Grad nach {richtung}.")
# Erzeuge den Ozobot
ozo = Ozobot(geschwindigkeit=4, top_light_color=[0, 0, 1])
seitenlaenge = 5
geschwindigkeit = 4
for _ in range(4):
ozo.geradeaus(seitenlaenge)
ozo.drehen(richtung="rechts", grad=90, geschwindigkeit=90)
Aufgabe 2:¶
Ergänzen Sie den Code aus Aufgabe 1 und erstellen Sie eine weitere Ozobot-Instanz bzw. Ozobot-Objekt. Dieser Ozo soll nun rot leuchten, 8cm/s schnell fahren und das Quadrat in anderer Richtung abfahren.
import ozobot
import math
# Definiere eine Klasse für den Ozobot
class Ozobot:
def __init__(self, geschwindigkeit, top_light_color=[1, 1, 1]):
# Initialisierung des Ozobot mit einer Instanz
self.ozo = ozobot.get_robot()
self.top_light_color = top_light_color
self.geschwindigkeit = geschwindigkeit / 100 # Anpassung für movement-Methoden
self.set_top_light(top_light_color)
print("Der Ozo ist bereit!")
def set_top_light(self, color):
r = color[0]
g = color[1]
b = color[2]
self.ozo.light_effects.set_light_color_rgb(r, g, b, ozobot.Lights.TOP)
def geradeaus(self, distanz_cm):
"""Ozo fährt Distanz in cm geradeaus. Mit der Geschwindigkeit in cm/s"""
distanz_cm /= 100 # Umrechnung für move-Methode
self.ozo.movement.move(distanz_cm, self.geschwindigkeit)
print(f"Ozobot fährt {distanz_cm * 100} cm geradeaus.")
def drehen(self, richtung, grad, geschwindigkeit):
"""Dreht x Grad mit Geschwindigkeit in Grad pro Sekunde. Standardmäßig nach rechts. Mit richtung="links" nach links."""
if richtung == "links":
self.ozo.movement.rotate(math.radians(grad), math.radians(geschwindigkeit))
else:
self.ozo.movement.rotate(math.radians(-grad), math.radians(geschwindigkeit))
print(f"Ozobot dreht {grad} Grad nach {richtung}.")
# Erzeuge den Ozobot
ozo = Ozobot(geschwindigkeit=8, top_light_color=[1, 0, 0]) # Blau
# Fahre ein Quadrat mit 5 cm Seitenlänge
seitenlaenge = 5 # cm
geschwindigkeit = 8 # cm/s
for _ in range(4):
ozo.geradeaus(seitenlaenge) # Geradeaus fahren
ozo.drehen(richtung="links", grad=-90, geschwindigkeit=90) # Nach rechts drehen
Aufgabe 3:¶
import ozobot
import math
# Definiere eine Klasse für den Ozobot
class Ozobot:
def __init__(self, geschwindigkeit, top_light_color = [1,1,1]):
# Initialisierung des Ozobot mit einer Instanz
self.ozo = ozobot.get_robot()
self.top_light_color = top_light_color
self.__geschwindigkeit = geschwindigkeit/100 # Anpassung für movement-Methoden
self.set_top_light(top_light_color)
print("Der Ozo ist bereit!")
def get_geschwindigkeit():
return self.__geschwindigkeit
def set_geschwindigkeit(self, geschwindigkeit):
if geschwindigkeit >= 1 and geschwindigkeit <= 10: #Wert von 1 bis 10
self.__geschwindigkeit = geschwindigkeit/100 #die geschwindigkeit wird übertragen
print (f"ihre geschwindigkeit beträgt {self.__geschwindigkeit}.")
else:
print("Die geschwindigkeit muss zwischen 1 und 10 sein")
def set_top_light (self, color):
r = color[0]
g = color[1]
b = color[2]
self.ozo.light_effects.set_light_color_rgb(r,g,b, ozobot.Lights.TOP)
def geradeaus(self, distanz_cm):
"""Ozo fährt Distanz in cm geradeaus. Mit der Geschwindikeit in cm/s"""
distanz_cm /= 100 # Umrechnung für move-Methode
self.ozo.movement.move(distanz_cm, self.__geschwindigkeit)
print(f"Ozobot fährt {distanz_cm} geradeaus.")
def drehen(self, richtung, grad, geschwindigkeit):
"""Dreht x grad mit geschwindigkeit in grad pro Sekunde standarmässig nach rechts. Mit richtung ="links" nach links."""
if richtung == "links":
self.ozo.movement.rotate(math.radians(grad), math.radians(geschwindigkeit))
else:
self.ozo.movement.rotate(math.radians(-grad), math.radians(geschwindigkeit))
print(f"Ozobot dreht {grad} Grad nach rechts.")
def rw_fahren(self, distanz_cm):
distanz_cm /= 100 # Umrechnung für move-Methode
self.ozo.movement.move(distanz_cm, self.__geschwindigkeit)
print(f"Ozobot fährt {distanz_cm} geradeaus.")
ozo1 = Ozobot(1, [0, 1.0, 0])
ozo1.geradeaus(5)
ozo1.set_geschwindigkeit(51)
ozo1.rw_fahren(-10) # Änderung Geschwindigkeit
ozo1.set_geschwindigkeit(10)
ozo1.geradeaus(10)eschwindigkeit(15) # Ungültig: Geschwindigkeit bleibt unverändert
Anpassungen:
-
set_geschwindigkeitMethode angepasst, um nur die Geschwindigkeit zu setzen (Entfernung desrichtung-Parameters). -
Konstruktor (
__init__) geändert, um nur die Geschwindigkeit zu übergeben, ohnerichtung. -
Fehlerbehebung beim Aufruf von
set_geschwindigkeit, sodass die Geschwindigkeit korrekt gesetzt wird. -
Direkter Zugriff auf
geschwindigkeitblockiert durch den Setter, der eineValueErrorwirft, wenn jemand versucht, den Wert direkt zu ändern.
Aufgabe 4¶
Aufgabe:
Lassen Sie den OzoAdvanced nun mit Toplight rot und Frontlights grün RÜCKWÄRTS ein Dreieck mit 5 cm Seitenlänge fahren
Wir haben am Code etwa 1 Stunde ausprobiert und haben dann den Code von jemandem übernommen.
# Importiere die Ozobot-Bibliothek
import ozobot
import math
# Definiere eine Klasse für den Ozobot
class Ozobot:
def __init__(self, geschwindigkeit, top_light_color=[1, 1, 1]):
self.ozo = ozobot.get_robot()
self.top_light_color = top_light_color
self._geschwindigkeit = geschwindigkeit / 100 # Anpassung für movement-Methoden
self.set_top_light(top_light_color)
print("Der Ozo ist bereit!")
def set_top_light(self, color):
r, g, b = color
self.ozo.light_effects.set_light_color_rgb(r, g, b, ozobot.Lights.TOP)
def set_geschwindigkeit(self, richtung, wert):
if richtung not in ["vorwaerts", "rueckwaerts"]:
print("Ungültige Richtung! Benutze 'vorwaerts' oder 'rueckwaerts'.")
return
if 1 <= wert <= 10:
self._geschwindigkeit = (wert / 100) * (-1 if richtung == "rueckwaerts" else 1)
print(f"Geschwindigkeit auf {wert} cm/s in Richtung {richtung} gesetzt.")
else:
print("Geschwindigkeit außerhalb des gültigen Bereichs (1-10 cm/s). Kein Update durchgeführt.")
def geradeaus(self, distanz_cm):
distanz_cm /= 100 # Umrechnung für move-Methode
self.ozo.movement.move(distanz_cm, self._geschwindigkeit)
print(f"Ozobot fährt {distanz_cm * 100} cm geradeaus.")
def drehen(self, richtung, grad, geschwindigkeit):
if richtung == "links":
self.ozo.movement.rotate(math.radians(grad), math.radians(geschwindigkeit))
else:
self.ozo.movement.rotate(math.radians(-grad), math.radians(geschwindigkeit))
print(f"Ozobot dreht {grad} Grad nach {richtung}.")
# Definiere die Unterklasse OzoAdvanced
class OzoAdvanced(Ozobot):
def __init__(self, geschwindigkeit, top_light_color=[1, 1, 1], front_light_color=[1, 1, 1]):
super().__init__(geschwindigkeit, top_light_color)
self.front_light_color = front_light_color
self.set_front_light(front_light_color)
def set_front_light(self, color):
try:
print(f"Frontlichter auf Farbe RGB {color} gesetzt.")
r, g, b = color
self.ozo.light_effects.set_light_color_rgb(r, g, b, ozobot.Lights.ALL_FRONT) #Im Ozoboz API Documentation steht das man alle lichter mit ALL_FRONT benutzen kann
except AttributeError:
print("Die Steuerung der Frontlichter wird von der aktuellen Ozobot-Bibliothek nicht unterstützt.")
def dreieck(self, seitenlaenge):
for _ in range(3):
self.geradeaus(seitenlaenge)
self.drehen("links", 120, 90) # Ein gleichseitiges Dreieck hat 120°-Winkel
print(f"Ozo hat ein Dreieck mit Seitenlänge {seitenlaenge} cm gefahren.")
ozo_adv = OzoAdvanced(geschwindigkeit=8, top_light_color=[1, 0, 0], front_light_color=[0, 1, 0]) # Toplight rot, Frontlight grün
ozo_adv.set_geschwindigkeit("rueckwaerts", 5) # Rückwärts mit Geschwindigkeit 5
ozo_adv.dreieck(5) # Dreieck mit 5 cm Seitenlänge
Aufgabe 5¶
Aufgabe:
| Läufer | Objekt |
|---|---|
| Läufer 1 | ozo1 (Klasse Ozobot, Farbe grün, Geschwindigkeit 5) Staffelübergabedauer 0,5s |
| Läufer 2 | ozo2(rot,7) Staffelübergabedauer 0,5s |
| Läufer 3 | ozo3(blau,7) |
| Läufer 4 | ozo4(gelb,10) |
| Siegesfeier | Schleife mit allen Läufern (ozo1-ozo4) und einem ozo_fans aus der Klasse OzoAdvanced: Mehrmals nacheinander die Läufer und die Fans (set_front_lights, dreieck) kurze, aber schnelle Bewegungen ausführen lassen |
Hinweis: Bei der Siegesfeier arbeiten die Top-Light-Farben nicht wie
gewünscht. Programmieren Sie eine Getter-Methode für die Top-Lights und
weisen Sie den Farbwert (Array) der set_top_light-Methode zu.
Wissen Sie warum sich die Farben sonst nicht ändern ❓
Code für Aufgabe 5:
# Importiere die Ozobot-Bibliothek
import ozobot
import math
import time
# Definiere die Klasse Ozobot
class Ozobot:
def __init__(self, geschwindigkeit, top_light_color=[1, 1, 1]):
self.ozo = ozobot.get_robot()
self._top_light_color = top_light_color
self._geschwindigkeit = geschwindigkeit / 100 # Anpassung für movement-Methoden
self.set_top_light(top_light_color)
print("Der Ozo ist bereit!")
def set_top_light(self, color):
"""Setzt die Farbe des Top-Lichts."""
self._top_light_color = color
r, g, b = color
self.ozo.light_effects.set_light_color_rgb(r, g, b, ozobot.Lights.TOP)
def get_top_light(self):
"""Gibt die aktuelle Farbe des Top-Lichts zurück."""
return self._top_light_color
def set_front_light(self, color):
"""Setzt die Farbe der Frontlichter."""
r, g, b = color
try:
self.ozo.light_effects.set_light_color_rgb(r, g, b, ozobot.Lights.ALL_FRONT)
print(f"Frontlichter auf Farbe RGB {color} gesetzt.")
except AttributeError:
print("Frontlichter werden von der Bibliothek nicht unterstützt.")
def set_geschwindigkeit(self, richtung, wert):
if richtung not in ["vorwaerts", "rueckwaerts"]:
print("Ungültige Richtung! Benutze 'vorwaerts' oder 'rueckwaerts'.")
return
if 1 <= wert <= 10:
self._geschwindigkeit = (wert / 100) * (-1 if richtung == "rueckwaerts" else 1)
print(f"Geschwindigkeit auf {wert} cm/s in Richtung {richtung} gesetzt.")
else:
print("Geschwindigkeit außerhalb des gültigen Bereichs (1-10 cm/s). Kein Update durchgeführt.")
def geradeaus(self, distanz_cm):
distanz_cm /= 100 # Umrechnung für move-Methode
self.ozo.movement.move(distanz_cm, self._geschwindigkeit)
print(f"Ozobot fährt {distanz_cm * 100} cm geradeaus.")
def drehen(self, richtung, grad, geschwindigkeit):
if richtung == "links":
self.ozo.movement.rotate(math.radians(grad), math.radians(geschwindigkeit))
else:
self.ozo.movement.rotate(math.radians(-grad), math.radians(geschwindigkeit))
print(f"Ozobot dreht {grad} Grad nach {richtung}.")
# 4x5 geradeaus mit Lichtwechsel
def fahren_geradeaus(ozo, runden, distanz_cm):
"""Lässt den Ozobot 4x5 cm geradeaus fahren und bei jeder Runde Top- und Front-Lights wechseln."""
farben = [
{"top": [0, 1, 0], "front": [0, 1, 0]}, # Grün Toplight, Rot Frontlight
{"top": [1, 0, 0], "front": [1, 0, 0]}, # Rot Toplight, Blau Frontlight
{"top": [0, 0, 1], "front": [0, 0, 1]}, # Blau Toplight, Gelb Frontlight
{"top": [1, 1, 0], "front": [1, 1, 0]} # Gelb Toplight, Türkis Frontlight
]
for runde in range(runden):
# Setze die Farben für Top- und Frontlights für die aktuelle Runde
ozo.set_top_light(farben[runde % len(farben)]["top"])
ozo.set_front_light(farben[runde % len(farben)]["front"])
print(f"Runde {runde + 1}: Toplight und Frontlight gesetzt.")
# Fährt geradeaus
ozo.geradeaus(distanz_cm) # Fährt die Distanz in cm
time.sleep(1) # Pause zwischen den Wiederholungen
# Siegesfeier
def siegesfeier(laeufer, fans):
"""Lässt die Läufer und Fans kurze Bewegungen und Lichtwechsel ausführen."""
for _ in range(3): # Wiederholung der Siegesfeier
for ozo in laeufer:
ozo.drehen("links", 90, 200) # Drehe 90 Grad links
ozo.set_front_light([1, 0, 0]) # Weißes Toplight
time.sleep(0.25)
ozo.set_front_light([0, 0, 1])
fans.drehen("rechts", 120, 300) # Fans drehen schneller
fans.set_front_light([0, 1, 1]) # Fans mit türkisen Frontlichtern
fans.geradeaus(3) # Fans bewegen sich kurz vorwärts
time.sleep(0.5)
# Hauptprogramm
ozo1 = Ozobot(5, [0, 1, 0]) # Läufer 1: Grün
ozo2 = Ozobot(7, [1, 0, 0]) # Läufer 2: Rot
ozo3 = Ozobot(7, [0, 0, 1]) # Läufer 3: Blau
ozo4 = Ozobot(10, [1, 1, 0]) # Läufer 4: Gelb
ozo_fans = Ozobot(8, [1, 1, 1]) # Fans: Weißes Toplight
# Fahren und Siegesfeier
fahren_geradeaus(ozo1, 4, 5) # Läufer 1 fährt 4x5 cm
siegesfeier([ozo1, ozo2, ozo3, ozo4], ozo_fans) # Siegesfeier mit allen Läufern und Fans
wir konnten es dann mit einer for-schleife umsetzen:)
Fragen:¶
- Warum
distanz_cm /= 100?
Die Zeile distanz_cm /= 100 teilt die Distanz in Zentimetern durch 100, um sie in Meter umzurechnen, da die move-Methode des Ozobots die Distanz in Metern erwartet.
- Wie haben Sie den zweiten Ozo aus Aufgabe 2 instanziiert?
Ich habe denn ersten Ozo abgeändert da ich das nicht so genau gelesen habe aber wenn ich es gemacht hätte, hätte ich ein neuse Objekt namens Ozo2 erstellt.
- Um welches Konzept der OoP geht es in Aufgabe 3? Was ist ein Setter/Getter? Was ist der Sinn?
In Aufgabe 3 geht es um das Konzept der Datenkapselung in der objektorientierten Programmierung (OOP), bei dem Setter- und Getter-Methoden verwendet werden.
-
Setter: Ermöglicht das sichere Setzen von Werten für private Attribute.
-
Getter: Ermöglicht das Zugreifen auf private Attribute.
Sinn von Settern und Gettern:
-
Zugangskontrolle: Sie schützen private Attribute vor unkontrolliertem Zugriff.
-
Validierung: Sie erlauben die Prüfung der Eingabewerte, bevor sie gespeichert werden.
-
Flexibilität: Änderungen an den Attributen können vorgenommen werden, ohne den restlichen Code zu beeinflussen.
-
Schutz der Integrität: Sie sichern die Datenintegrität und verhindern direkte Manipulationen.
- Um welches Konzept der OoP geht es in Aufgabe 4?
In Aufgabe 4 wird das Vererbungskonzept angewendet, bei dem die Unterklasse (OzoAdvanced) von der Elternklasse (Ozobot) erbt und zusätzlich neue Funktionalitäten hinzufügt.
- Aufgabe 5 Staffellauf: Warum ändern sich die Farben nicht? Wie konnten Sie das lösen?
Wir haben dies wie oben beschrieben mit einer for-schleife umgesetzt in dem wir immer wieder die Farben abgeändert haben sodass sie nacher richtig funktioniert haben.
GUI-Kaffee¶
Erweitern Sie die objektorientierte Variante mit KI-Hilfe um eine GUI. Die GUI soll die Maschine grob darstellen und es soll möglich sein eine Auswahl der Kaffeesorten auszuwählen und zu bezahlen.
Ich habe die main.py und die kaffeemaschine.py der KI gegeben und den folgenden Output erhalten:
import tkinter as tk
from tkinter import messagebox
from kaffeemaschine import Kaffeeautomat
class KaffeeautomatGUI:
def __init__(self, root):
self.root = root
self.root.title("Kaffeeautomat")
self.automat = Kaffeeautomat()
# GUI Aufbau
self.create_widgets()
def create_widgets(self):
# Begrüßung
welcome_label = tk.Label(self.root, text="Willkommen beim Kaffeeautomat", font=("Helvetica", 16, "bold"))
welcome_label.pack(pady=10)
# Auswahl-Menü
self.selection_var = tk.StringVar(value="Espresso")
selection_label = tk.Label(self.root, text="Wählen Sie ein Getränk:")
selection_label.pack()
for drink in self.automat.menu.keys():
rb = tk.Radiobutton(self.root, text=f"{drink} - CHF {self.automat.menu[drink]['preis']:.2f}",
variable=self.selection_var, value=drink)
rb.pack(anchor=tk.W)
# Button zur Bestellung
order_button = tk.Button(self.root, text="Bestellen", command=self.bestellung_durchfuehren)
order_button.pack(pady=10)
# Status-Anzeige
status_button = tk.Button(self.root, text="Maschinenstatus anzeigen", command=self.status_anzeigen)
status_button.pack(pady=5)
# Ressourcen auffüllen
refill_button = tk.Button(self.root, text="Ressourcen auffüllen", command=self.ressourcen_auffuellen)
refill_button.pack(pady=5)
# Textbereich für Ausgaben
self.output_text = tk.Text(self.root, height=10, width=40, state=tk.DISABLED)
self.output_text.pack(pady=10)
def bestellung_durchfuehren(self):
auswahl = self.selection_var.get()
drink_info = self.automat.menu[auswahl]
preis = drink_info['preis']
if not self.automat.reichen_ressourcen(drink_info['zusammensetzung']):
self.ausgabe_anzeigen(f"Nicht genug Ressourcen für {auswahl}.")
return
# Simulierte Zahlung
geld = self.geld_eingabe(preis)
if geld >= preis:
self.automat.ist_geld_ausreichend(geld, preis)
self.automat.kaffee_ausgeben(auswahl)
self.ausgabe_anzeigen(f"Ihr {auswahl} wurde zubereitet! Geniessen Sie Ihren Kaffee ☕")
else:
self.ausgabe_anzeigen("Zahlung fehlgeschlagen. Nicht genug Geld eingegeben.")
def geld_eingabe(self, preis):
geld_popup = tk.Toplevel(self.root)
geld_popup.title("Geldeingabe")
tk.Label(geld_popup, text=f"Bitte geben Sie mindestens CHF {preis:.2f} ein:").pack()
geld_var = tk.DoubleVar(value=0)
tk.Entry(geld_popup, textvariable=geld_var).pack()
def submit_geld():
geld_popup.destroy()
submit_button = tk.Button(geld_popup, text="Bestätigen", command=submit_geld)
submit_button.pack()
geld_popup.wait_window()
return geld_var.get()
def status_anzeigen(self):
status = f"Wasser: {self.automat.ressourcen['wasser']}ml\n"
status += f"Milch: {self.automat.ressourcen['milch']}ml\n"
status += f"Kaffeebohnen: {self.automat.ressourcen['kaffeebohnen']}g\n"
status += f"Eingenommenes Geld: CHF {self.automat.geldbetrag:.2f}"
messagebox.showinfo("Maschinenstatus", status)
def ressourcen_auffuellen(self):
self.automat.ressourcen["wasser"] += 300
self.automat.ressourcen["milch"] += 200
self.automat.ressourcen["kaffeebohnen"] += 100
self.ausgabe_anzeigen("Ressourcen wurden erfolgreich aufgefüllt!")
def ausgabe_anzeigen(self, text):
self.output_text.config(state=tk.NORMAL)
self.output_text.insert(tk.END, text + "\n")
self.output_text.config(state=tk.DISABLED)
if __name__ == "__main__":
root = tk.Tk()
app = KaffeeautomatGUI(root)
root.mainloop()
ich habe dann denn Code ausgeführt und es hat sich folgendes Fenster geöffnet:
es hat mir aber nur das terminal gemacht des automaten und keinen richtigen kaffeeautomat aber alles funktionierte und ich habe dann nochmals nachgehakt und es nochmals probiert und es sah dann so aus:

ich habe dann der KI gesagt sie soll es so anpassen das es stimmt und so sah es dann aus:

Die KI hat es zwar geschafft wenn ich das Fenster kleiner oder grösser mache die sachen anzupassen sodass sie nicht verrutschen aber konnte es nicht auf genau die maschine einsetzen. Ich glaube wenn das Bild im hintergrund stimmt dann sollte es kein Problem sein so etwas zu erstellen. Ich habe die Kaffeemaschine natürlich auch auf funktionalität getestet und es funktioniert alles. Jeder Knopf und jede Eingabe gibt einen Output. Hier ist der Code dazu:
import tkinter as tk
from tkinter import messagebox, PhotoImage
from kaffeemaschine import Kaffeeautomat
class KaffeeautomatGUI:
def __init__(self, root):
self.root = root
self.root.title("Kaffeeautomat")
self.automat = Kaffeeautomat()
# Hintergrundbild
self.background_image = PhotoImage(file="kaffeeordner/kaffeemaschine.png")
self.canvas = tk.Canvas(self.root, width=self.background_image.width(), height=self.background_image.height())
self.canvas.pack()
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.background_image)
# Widgets platzieren
self.create_widgets()
def create_widgets(self):
# Auswahl-Label und Buttons
self.canvas.create_text(200, 50, text="Wählen Sie Ihr Getränk:", font=("Helvetica", 14, "bold"), fill="black")
self.selection_var = tk.StringVar(value="Espresso")
y_offset = 80
for drink in self.automat.menu.keys():
preis = self.automat.menu[drink]["preis"]
rb = tk.Radiobutton(self.root, text=f"{drink} - CHF {preis:.2f}", variable=self.selection_var, value=drink,
bg="white")
self.canvas.create_window(200, y_offset, window=rb)
y_offset += 30
# Buttons
self.create_button("Bestellen", self.bestellung_durchfuehren, 200, 220)
self.create_button("Maschinenstatus", self.status_anzeigen, 200, 260)
self.create_button("Ressourcen auffüllen", self.ressourcen_auffuellen, 200, 300)
# Geld einwerfen
self.canvas.create_text(200, 340, text="Geld einwerfen (CHF):", font=("Helvetica", 10), fill="black")
self.geld_var = tk.DoubleVar(value=0)
self.geld_entry = tk.Entry(self.root, textvariable=self.geld_var)
self.canvas.create_window(200, 370, window=self.geld_entry)
self.create_button("Geld bestätigen", self.geld_bestätigen, 200, 400)
# Textbereich für Ausgaben
self.output_text = tk.Text(self.root, height=5, width=40, state=tk.DISABLED, bg="lightgrey")
self.canvas.create_window(200, 460, window=self.output_text)
def create_button(self, text, command, x, y):
button = tk.Button(self.root, text=text, command=command, bg="lightgrey")
self.canvas.create_window(x, y, window=button)
def bestellung_durchfuehren(self):
auswahl = self.selection_var.get()
preis = self.automat.menu[auswahl]["preis"]
geld = self.geld_var.get()
if self.automat.reichen_ressourcen(self.automat.menu[auswahl]["zusammensetzung"]):
if geld >= preis:
self.automat.kaffee_ausgeben(auswahl)
self.ausgabe_anzeigen(f"Ihr {auswahl} wurde zubereitet! ☕")
self.geld_var.set(0)
self.geld_entry.delete(0, tk.END)
else:
self.ausgabe_anzeigen("Nicht genug Geld eingegeben.")
else:
self.ausgabe_anzeigen(f"Nicht genug Ressourcen für {auswahl}.")
def geld_bestätigen(self):
geld = self.geld_var.get()
self.ausgabe_anzeigen(f"CHF {geld:.2f} eingegeben.")
def status_anzeigen(self):
status = f"Wasser: {self.automat.ressourcen['wasser']}ml\n"
status += f"Milch: {self.automat.ressourcen['milch']}ml\n"
status += f"Kaffeebohnen: {self.automat.ressourcen['kaffeebohnen']}g\n"
status += f"Eingenommenes Geld: CHF {self.automat.geldbetrag:.2f}"
messagebox.showinfo("Maschinenstatus", status)
def ressourcen_auffuellen(self):
self.automat.ressourcen["wasser"] += 300
self.automat.ressourcen["milch"] += 200
self.automat.ressourcen["kaffeebohnen"] += 100
self.ausgabe_anzeigen("Ressourcen wurden erfolgreich aufgefüllt!")
def ausgabe_anzeigen(self, text):
self.output_text.config(state=tk.NORMAL)
self.output_text.insert(tk.END, text + "\n")
self.output_text.config(state=tk.DISABLED)
if __name__ == "__main__":
root = tk.Tk()
app = KaffeeautomatGUI(root)
root.mainloop()

