Einstieg - Grafische Benutzeroberflächen zur Roboterwelt
Grafische Darstellung der Roboterwelt
Mit Hilfe einer grafischen Benutzeroberfläche (GUI) soll das System zur Simulation eines Roboters benutzerfreundlich gestaltet werden. Ziel ist es, eine Roboterwelt wie die folgende
grafisch so darzustellen.
Da es nicht so einfach ist, eine solche Benutzeroberfläche zu entwickeln, werden wir hier schrittweise vorgehen.
Textuelle Darstellung des Roboters
Ziel ist es, zunächst eine sehr einfache grafische Benutzeroberfläche zur Steuerung des Roboters zu entwickeln.
Der Roboter wird mit Hilfe von drei Schaltflächen gesteuert. Die jeweilge Position des Roboters wird auf einem Schriftfeld textuell dargestellt.
Wir gehen davon aus, dass das Datenmodell in der Datei
_roboterwelt.txt (die man in roboterwelt.py
umbenennen sollte)
deklariert ist
und eine Basisversion der Klasse Roboter
enthält.
Das folgende Programm erzeugt (in Teilen) die oben gezeigte grafische Benutzeroberfläche:
#--------------------------------------------------------------
# Datenmodell
#--------------------------------------------------------------
from roboterwelt import *
welt = Welt(5, 5)
rob = Roboter()
rob.setWelt(welt)
#--------------------------------------------------------------
# GUI
#--------------------------------------------------------------
from tkinter import *
def buttonSchrittClick():
rob.schritt()
labelAusgabe.config(text=str(rob.getZustand()))
# Erzeugung des Fensters
fenster = Tk()
fenster.title("Roboterwelt")
fenster.geometry('330x330')
# Rahmen
rahmenRoboter = Frame(master=fenster, background="gray")
rahmenRoboter.place(x=5, y=5, width=320, height=320)
# Label
labelAusgabe = Label(master=rahmenRoboter, background="white",
text=str(rob.getZustand()))
labelAusgabe.place(x=78, y=18, width=164, height=164)
# Button schritt
buttonSchritt = Button(master=rahmenRoboter, text="schritt",
command=buttonSchrittClick)
buttonSchritt.place(x=110, y=200, width=100, height=27)
# Aktivierung der Ereignisschleife
fenster.mainloop()
Aufgabe 1
Analysiere und teste das Programm. Ergänze die fehlenden Teile (Schaltflächen zum Links- und Rechtsdrehen).
Aufgabe 2
(a) Wie viele Objekte werden im Programm oben erzeugt? Verdeutliche die Situation mit einem Objektdiagramm.
(b) Das Programm ist (auch optisch) in zwei Bereiche aufgeteilt: Datenmodell- und GUI-Bereich. Welche Aufgaben erfüllen das Objekt im Datenmodellbereich, welche die im GUI-Bereich?
Ein Objekt zur Verwaltung der GUI-Komponenten
Das bisher betrachtete Programm zu der oben gezeigten grafischen Benutzeroberfläche hat folgende Objekt-Struktur:
...
#--------------------------------------------------------------
# Datenmodell
#--------------------------------------------------------------
...
welt = Welt(5, 5)
rob = Roboter()
rob.setWelt(welt)
#--------------------------------------------------------------
# GUI
#--------------------------------------------------------------
...
# Erzeugung des Fensters
fenster = Tk()
...
# Label
labelAusgabe = Label(master=rahmenRoboter, background="white",
text=str(rob.getZustand()))
...
# Button schritt
buttonSchritt = Button(master=rahmenRoboter, text="schritt",
command=buttonSchrittClick)
...
Mit einem Objektdiagramm lässt sich diese Struktur so darstellen:
Neben den Datenmodell-Objekten gibt es eine Vielzahl von Objekten zur Verwaltung der GUI-Komponenten.
Die Objekte zur Verwaltung der GUI-Komponenten sollen künftig von einem Manager
-Objekt
gui
erzeugt und verwaltet werden.
Dieses Manager
-Objekt gui
soll zudem Zugriff auf die Datenmodell-Objekte haben.
Das folgende Objektdiagramm verdeutlicht die gewünschte Struktur:
Diese Struktur wird von dem folgenden Programm erzeugt:
from tkinter import *
from roboterwelt import *
class Gui(object):
def __init__(self, rob, welt):
# Referenzattribute zum Datenmodell
self.rob = rob
self.welt = welt
# Erzeugung des Fensters
self.fenster = Tk()
self.fenster.title("Roboterwelt")
self.fenster.geometry('330x330')
# Rahmen
self.rahmenRoboter = Frame(master=self.fenster, background="gray")
self.rahmenRoboter.place(x=5, y=5, width=320, height=320)
# Label
self.labelAusgabe = Label(master=self.rahmenRoboter, background="white",
text=str(self.rob.getZustand()))
self.labelAusgabe.place(x=78, y=18, width=164, height=164)
# Button links
self.buttonLinks = Button(master=self.rahmenRoboter, text="links",
command=self.buttonLinksClick)
self.buttonLinks.place(x=5, y=200, width=100, height=27)
# Button schritt
self.buttonSchritt = Button(master=self.rahmenRoboter, text="schritt",
command=self.buttonSchrittClick)
self.buttonSchritt.place(x=110, y=200, width=100, height=27)
# Button rechts
self.buttonRechts = Button(master=self.rahmenRoboter, text="rechts",
command=self.buttonRechtsClick)
self.buttonRechts.place(x=215, y=200, width=100, height=27)
# Ereignisschreife
self.fenster.mainloop()
def buttonSchrittClick(self):
self.rob.schritt()
self.labelAusgabe.config(text=str(self.rob.getZustand()))
def buttonLinksClick(self):
self.rob.links()
self.labelAusgabe.config(text=str(self.rob.getZustand()))
def buttonRechtsClick(self):
self.rob.rechts()
self.labelAusgabe.config(text=str(self.rob.getZustand()))
# Erzeugung der Datenmodell-Objekte
welt = Welt(5, 5)
rob = Roboter()
rob.setWelt(welt)
# Erzeugung des Gui-Objekts
gui = Gui(rob, welt)
Aufgabe 3
Teste und analysiere das Programm.
Aufgabe 4
Zeichne ein Klassendiagramm zum gezeigten Programm. Berücksichtige hierbei, welche Objektbeziehungen kennt-Beziehungen bzw. hat-Beziehungen sind.
Von der textuellen Ausgabe zur grafischen Darstellung
Die textuelle Ausgabe des Roboterzustands soll durch eine grafische Darstellung der Roboterwelt ersetzt werden:
Die Bausteine zur Erstellung der Grafiken werden hier bereitgestellt.
Das bisher entwickelte Programm mit einer textuellen Ausgabe des Roboterzustands hat folgende Klassen-Struktur:
Ein Gui
-Objekt hat die volle Kontrolle über die Objekte zur Verwaltung der GUI-Komponenten,
u. a. also auch über ein Label
-Objekt, das für die Ausgabe der Roboterdaten zuständig ist.
Um aus einer textuellen Ausgabe eine grafische Darstellung zu erhalten, wird zunächst das Label
-Objekt
gegen ein Canvas
-Objekt ausgetauscht:
Zudem werden Hilfsoperationen erzeugeWeltGrafik
, erzeugeRoboterGrafik
,
aktualisiereWeltGrafik
und aktualisiereRoboterGrafik
zur Erzeugung und Aktualisierung
der jeweiligen grafischen Darstellung der Roboterwelt deklariert.
Die Struktur des Programms ist im folgenden Quelltextauszug zu sehen:
from tkinter import *
from roboterwelt import *
#---------------------------------------------------------------------------------
class Gui(object):
def __init__(self, rob, welt):
# Referenzattribute zum Datenmodell
self.rob = rob
self.welt = welt
# Erzeugung des Fensters
self.fenster = Tk()
self.fenster.title("Roboterwelt")
self.fenster.geometry('330x330')
# Rahmen
self.rahmenRoboter = Frame(master=self.fenster, background="gray")
self.rahmenRoboter.place(x=5, y=5, width=320, height=320)
# Canvas
self.canvas = Canvas(master=self.rahmenRoboter, background="white",
width=164, height=164)
self.canvas.place(x=78, y=18)
self.erzeugeWeltGrafik()
self.erzeugeRoboterGrafik()
# Button schritt
self.buttonSchritt = Button(master=self.rahmenRoboter, text="schritt",
command=self.buttonSchrittClick)
self.buttonSchritt.place(x=110, y=200, width=100, height=27)
...
# Button Marke setzen
self.buttonMarkeSetzen = Button(master=self.rahmenRoboter,
text="Marke setzen",
command=self.buttonMarkeSetzenClick)
self.buttonMarkeSetzen.place(x=5, y=240, width=100, height=27)
...
# Ereignisschreife
self.fenster.mainloop()
def erzeugeWeltGrafik(self):
...
def erzeugeRoboterGrafik(self):
...
def aktualisiereWeltGrafik(self):
...
def aktualisiereRoboterGrafik(self):
...
def buttonSchrittClick(self):
self.rob.schritt()
self.aktualisiereRoboterGrafik()
...
def buttonMarkeSetzenClick(self):
self.rob.markeSetzen()
self.aktualisiereWeltGrafik()
self.aktualisiereRoboterGrafik()
...
# Erzeugung der Datenmodell-Objekte
welt = Welt(5, 5)
rob = Roboter()
rob.setWelt(welt)
# Erzeugung des Gui-Objekts
gui = Gui(rob, welt)
Aufgabe 5
(a) Lade die Dateien _roboterwelt.txt und gui_roboterwelt.txt herunter und ändere die Dateiendungen. Teste das gesamte Programm.
(b) Vergleiche das Programm zur Erzeugung der grafischen Benutzeroberfläche mit grafischer Darstellung der Roboterwelt mit dem entsprechenden Programm, bei dem eine textuelle Ausgabe des Roboterzustands erfolgt. An welchen Stellen sind Änderungen vorgenommen worden?