Datenmodell-GUI-Architektur
Grafische Benutzeroberfläche für eine Ampel
Ziel ist es, eine einfache grafische Benutzeroberfläche zu erzeugen, von der aus ein Objekt der Klasse Ampel
aktiviert werden kann.
Zur Verwaltung einer Ampel benutzen wir die bereits entwickelte Klasse Ampel
aus der Datei ampel.py.
Verwendung von GUI-Objekten
Der folgende Quelltext zeigt, wie man eine grafische Benutzeroberfläche zur Anzeige einer Ampel mit Hilfe von tkinter
-Objekten erzeugen kann.
from ampel import Ampel
ampel = Ampel('rot')
from tkinter import *
grau = '#404040'
rotAn = '#FF0000'
rotAus = '#550000'
gelbAn = '#FFFF00'
gelbAus = '#555500'
gruenAn = '#00FF00'
gruenAus = '#005500'
def buttonWeiterClick():
ampel.schalten()
(lampeRot, lampeGelb, lampeGruen) = ampel.getLampen()
if lampeRot:
canvas.itemconfigure(id_rot, fill=rotAn)
else:
canvas.itemconfigure(id_rot, fill=rotAus)
if lampeGelb:
canvas.itemconfigure(id_gelb, fill=gelbAn)
else:
canvas.itemconfigure(id_gelb, fill=gelbAus)
if lampeGruen:
canvas.itemconfigure(id_gruen, fill=gruenAn)
else:
canvas.itemconfigure(id_gruen, fill=gruenAus)
fenster = Tk()
fenster.title("Ampel")
fenster.geometry("400x300")
canvas = Canvas(master=fenster)
canvas.place(x=0, y=0, width=400, height=300)
hintergrundbild = PhotoImage(file="hintergrund.gif")
canvas.create_image(0, 0, image=hintergrundbild, anchor=NW)
canvas.create_rectangle(250, 120, 262, 152, fill=grau)
id_rot = canvas.create_oval(252, 122, 260, 130, fill=grau)
id_gelb = canvas.create_oval(252, 132, 260, 140, fill=grau)
id_gruen = canvas.create_oval(252, 142, 260, 150, fill=grau)
canvas.create_rectangle(255, 152, 257, 184, fill=grau)
(lampeRot, lampeGelb, lampeGruen) = ampel.getLampen()
if lampeRot:
canvas.itemconfigure(id_rot, fill=rotAn)
else:
canvas.itemconfigure(id_rot, fill=rotAus)
if lampeGelb:
canvas.itemconfigure(id_gelb, fill=gelbAn)
else:
canvas.itemconfigure(id_gelb, fill=gelbAus)
if lampeGruen:
canvas.itemconfigure(id_gruen, fill=gruenAn)
else:
canvas.itemconfigure(id_gruen, fill=gruenAus)
buttonWeiter = Button(master=fenster,
text="weiter",
command=buttonWeiterClick)
buttonWeiter.place(x=150, y=270, width=100, height=20)
fenster.mainloop()
Aufgabe 1
(a) Teste zunächst das GUI-Programm. Beachte, dass du hierzu ein Hintergrundbild in einer Datei hintergrund.gif
vorliegen muss.
(b) Welche Objekte werden hier zur Realisierung der grafischen Benutzeroberfläche erzeugt und benutzt?
Eine Klasse zur Beschreibung der GUI
Zur Strukturierung des Programms ist es günstig, die grafische Benutzeroberfläche mit Hilfe einer Klasse GUI
zu realisieren. Aufgabe eines Objektes der Klasse GUI
ist es, sämtliche tkinter
-Objekte zu verwalten, die zur Erzeugung der GUI benötigt werden. Zudem soll ein Objekt der Klasse GUI
die Ereignisverarbeitung übernehmen.
from ampel import Ampel
from tkinter import *
grau = '#404040'
rotAn = '#FF0000'
rotAus = '#550000'
gelbAn = '#FFFF00'
gelbAus = '#555500'
gruenAn = '#00FF00'
gruenAus = '#005500'
class GUI(object):
def __init__(self, datenmodell):
self.ampel = datenmodell[0]
self.fenster = Tk()
self.fenster.title("Ampel")
self.fenster.geometry("400x300")
self.canvas = Canvas(master=self.fenster)
self.canvas.place(x=0, y=0, width=400, height=300)
self.hintergrundbild = PhotoImage(file="hintergrund.gif")
self.canvas.create_image(0, 0, image=self.hintergrundbild, anchor=NW)
self.canvas.create_rectangle(250, 120, 262, 152, fill=grau)
self.id_rot = self.canvas.create_oval(252, 122, 260, 130, fill=grau)
self.id_gelb = self.canvas.create_oval(252, 132, 260, 140, fill=grau)
self.id_gruen = self.canvas.create_oval(252, 142, 260, 150, fill=grau)
self.canvas.create_rectangle(255, 152, 257, 184, fill=grau)
self.anzeigeAktualisieren()
self.buttonWeiter = Button(master=self.fenster,
text="weiter",
command=self.buttonWeiterClick)
self.buttonWeiter.place(x=150, y=270, width=100, height=20)
def buttonWeiterClick(self):
self.ampel.schalten()
self.anzeigeAktualisieren()
def anzeigeAktualisieren(self):
(lampeRot, lampeGelb, lampeGruen) = self.ampel.getLampen()
if lampeRot:
self.canvas.itemconfigure(self.id_rot, fill=rotAn)
else:
self.canvas.itemconfigure(self.id_rot, fill=rotAus)
if lampeGelb:
self.canvas.itemconfigure(self.id_gelb, fill=gelbAn)
else:
self.canvas.itemconfigure(self.id_gelb, fill=gelbAus)
if lampeGruen:
self.canvas.itemconfigure(self.id_gruen, fill=gruenAn)
else:
self.canvas.itemconfigure(self.id_gruen, fill=gruenAus)
ampel = Ampel('rot')
datenmodell = [ampel]
gui = GUI(datenmodell)
gui.fenster.mainloop()
Aufgabe 2
(a) Teste zunächst das Programm (mit einem eigenen Hintergrundbild oder auch ohne Hintergrundbild). Mache dich anschließend mit dem Quelltext vertraut. Analysiere insbesondere die Ereignisverarbeitungsprozedur.
(b) Ergänze das Programm so, dass zwei Ampeln simuliert werden.
Aufgabe 3
In dieser Aufgabe geht es um die Objektstruktur des Software-Systems (mit GUI-Klasse).
(a) Begründe anhand des Quelltextes, dass u.a. folgende Objekte am Gesamtsystem beteiligt sind:
(b) Erkläre mit Hilfe des Quelltextes das folgende Klassendiagramm zum Software-System.
(c) Das Software-System benutzt eine 2-Schichten-Architektur: Die obere Schicht ist für die GUI zuständig, die untere für das Datenmodell. Warum ist es günstig, wenn in der unteren Schicht (d.h. im Datenmodell) keine Bezüge auf die obere Schicht (d.h. die GUI) genommen werden?