![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
// LinuxTag 2004
Besuchen Sie uns auch n臘hstes Jahr wieder auf dem LinuxTag 2004
im Karlsruher Messe- und Kongresszentrum. Fr n臧ere Details und den
genauen Termin besuchen Sie bitte die LinuxTag Homepage.
|
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
|
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
|
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
EUROPAS GRヨSSTE GNU/LINUX MESSE UND KONFERENZ KONFERENZ-CD-ROM 2003 |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
|
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
|
|
Hauptseite//Vortr臠e//Python als Basis fr komplexe GUI Anwendungen |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
Python als Basis fr komplexe GUI Anwendungen
Bernhard Herzog
Einfhrung
Dieser Vortrag gibt eine ワbersicht ber den Einsatz der
Programmiersprache Python zur Entwicklung umfangreicher und
komplexer Applikationen mit grafischer Benutzeroberfl臘he.
Insbesondere geht es um Python als Hauptentwicklungssprache,
eventuell kombiniert mit anderen Sprachen wie C oder C++, und
nicht darum, Python nur einzusetzen, um eine Skriptsprache in eine
bestehende Applikation einzufgen.
Zur Erl舫terung werden Beispiele aus zwei Projekten, Sketch und Thuban verwendet.
Sketch ist ein leistungsf臧iges Vektorzeichenprogramm fr
GNU/Linux und eines der umfangreichsten in Python geschriebenen
GUI-Programme (mit ca. 50000 Zeilen Pythoncode und 20000 Zeilen
C-Code). Sketch l舫ft unter Unix-臧nlichen Systemen mit X11 und
verwendet in der stabilen Version Tkinter (Pythons Tk-Anbindung)
und in der Entwicklerversion GTK 2).
Sketch bietet dem Benutzer au゚er den blichen F臧igkeiten eines
interaktiven Zeichenprogramms die Mlichkeit, eigene
Pythonfunktionen zu schreiben und in das Men einzubinden. Des
weiteren hat Sketch ein Plugin-System mit dem man Pythonmodule
schreiben kann, die automatisch eingebunden werden und mit denen
neue Import/Export Filter und sogar neue Objekttypen implementiert
werden knen.
Thuban ist ein Anwendung zum Betrachten von geographischen Daten.
Die Daten knen aus verschiedenen Quellen stammen, wobei zur Zeit
Shapefiles und PostGIS-Datenbanken untersttzt werden. PostGIS
untersttzung ist noch in der Entwicklung wird aber
voraussichtlich im Juni 2003 in Thuban zur Verfgung stehen.
Thuban verwendet wxPython als GUI-Toolkit und l舫ft unter
GNU/Linux (und vermutlich anderen Unix-臧nlichen Systemen) sowie
unter MS Windows.
Python
Python ist eine dynamisch typisierte, objektorientierte
Programmiersprache. Python wird seit ber 10 Jahren best舅dig
weiter entwickelt und erfreute sich besonders in den letzten
Jahren wachsender Beliebtheit. Die aktuelle stabile Version ist
2.2.2. Python 2.3 ist zur Zeit (Mai 2003) in Beta.
Da Python als solches nicht Teil des Vortrags ist hier nur eine
kurze ワbersicht ber die Eigenschaften der Sprache mit besonderem
Augenmerk auf die Dinge, die fr GUI-Programme interessant sind.
Dynamische Typisierung
Python ist dynamisch typisiert. Etwas vereinfacht ausgedrckt
hei゚t das, da゚ Typinformationen an Objekte und nicht an
Variablen geknpft sind. Typberprfungen finden zur Laufzeit
statt. Das hat mehrere Konsequenzen:
-
Pythoncode ist generisch in dem Sinne, da゚ eine Funktion
oder Methode mit allen Parametern funktioniert, die
bestimmte implizite Schnittstellen implementieren. Welche
Schnittstellen dies sind ist nur dadurch definiert, was die
Funktion mit den bergebenen Objekten macht aber nicht wie
sie deklariert ist. In dieser Hinsicht sind Python
Funktionen vergleichbar mit C++ Templates.
-
Python ist nicht so schnell wie kompilierte statisch
typisierte Sprachen. Das ist in der Praxis im Allgemeinen
kein grosses Problem, da meist nur relativ kleine Teile
eines Programms wirklich laufzeitkritisch sind, und selbst
diese h舫fig schnell genug sind.
Wenn ein Programm dennoch zu langsam ist, kann man zun臘hst
mit dem Profiler (ein Bestandteil der Standardbibliothek)
feststellen, welcher Teil des Codes das Problem ist und dann
entweder versuchen, bessere Algorithmen und/oder
Datenstrukturen einzusetzen oder, wenn das nicht
weiterhilft, den kritischen Teil in C oder C++ schreiben (s.
unten).
-
Typfehler werden erst zur Laufzeit entdeckt. Typfehler
bedeutet hier meist, da゚ ein Objekt nicht das vom Code
erwartete Interface implementiert. In manchen F舁len kann es
aber auch sein, da゚ speziell ein Integer erwartet wird und
z.B. ein Float verwendet wurde.
Fr Programmierer, die von statisch typisierten Sprachen her
kommen, ist dynamische Typisierung zumindest zu Anfang etwas
erschreckend, da ihnen das gewohnte Sicherheitsnetz der
Typprfung zur Compilezeit fehlt. Wenn man allerdings gute
Unittests hat, findet man diese Fehler in der Regel kurz
nachdem der fehlerhafte Code geschrieben wurde. Man sollte
auch bedenken, da゚ statische Typprfungen nur einen Teil der
mlichen Fehler eines Programms finden knen und man daher
auch in statisch typisierten Sprachen nicht auf (mlichst
automatische) Tests verzichten sollte.
Automatische Kompilierung
Python mu゚ nicht explizit bersetzt werden. Damit entf舁lt ein
separater ワbersetzungsschritt und man kann beim Programmieren
nach einer トnderung sein Programm einfach sofort neu starten.
Flexible Standarddatentypen
Die eingebauten Datentypen Dictionary (eine Hashtabelle), Listen
(eigentlich ein Array oder Vektor) sowie Strings (sowohl als
Bytestrings als auch als Unicode Objekte) erleichtern viele
Aspekte der Programmentwicklung.
Da diese Datentypen Standardbestandteil von Python sind, sind
ihre Implementationen im Laufe der Zeit sehr gut optimiert
worden. Dies gilt insbesondere fr die Dictionaries, mit denen
fast alle Namensr舫me implementiert. Ausserdem verfgt die
Sprache ber spezielle Syntax um die Objekte zu erzeugen und zu
verwenden:
unicode_string = u"Unicode"
langer_string = """Ein langer String,
der sich ber mehrere Zeilen
erstreckt"""
# eine Liste mit drei Elementen
liste = [1, 2, 10]
# Ein dictionary, das "a" auf 1 abbildet und das Tupel (1, 2) auf 4
dictionary = {"a": 1, (1, 2): 4}
# Eine "Listcomprehension" baut ein Liste aus einer Sequenz und
# einem Ausdruck (hier die ersten 10 Quadratzahlen):
quadratzahlen = [x ** 2 for x in range(10)]
|
Hohe Produktivit舩
Alle bisher aufgefhrten Eigenschaften kombiniert fhren zu
einer hohen Produktivit舩 der Programmierer, besonders im
Vergleich zu C oder C++.
Mit der dynamischen Typisierung und der damit verbundenen, eher
generischen Programmierweise reicht es meist, sich auf die
Schnittstellen seiner Objekte und die Operationen auf ihnen zu
konzentrieren. In statischen Sprachen muss man sich hingegen
schon recht frh auf sehr bestimme Datentypen festlegen. Wo man
in Python z.B. zun臘hst mal einfach an "Zahl" denkt muss man
sich in C sofort fr "int", "float" oder "unsigned int" oder
臧nliches entscheiden. Sp舩ere トnderungen ziehen dann h舫fig
viele トnderungen an anderen Stellen nach sich.
Die leistungsf臧igen und flexiblen Datentypen ermlichen es,
auf einer abstrakteren Ebene zu arbeiten und sorgen fr relativ
kompakten aber dennoch lesbaren Code und kurze
Entwicklungszeiten, da man sich um viele Details nicht kmmern
muss.
Die krzeren Implementationszeiten ermlichen es, im gleichen
Zeitraum eine grere Zahl verschiedener Algorithmen und
Datenstrukturen fr die Lung eines Problems auszuprobieren, so
da゚ man h舫fig zu einer besseren Lung gelangt, als mit C oder
C++ im gleichen Zeitraum mlich gewesen w舐e.
C-API
Python l舖st sich leicht durch C oder C++ Code erweitern.
Hauptanwendungsgebiete von solchen Erweiterungsmodulen sind
Anbindungen an externe Bibliotheken oder Optimierung.
Die C-API ermlicht alle blichen Operationen auf
Python-Objekten und erlaubt es, von Python aufrufbare Funktionen
zu schreiben und auch neue Datentypen fr Python zu definieren.
Seit Python 2.2 ist es auch mlich, Typen zu implementieren,
die man in Python wie eine Klasse beerben kann.
Die C-API ist bis auf wenige Ausnahmen sehr konsistent und,
etwas C und Python-Erfahrung vorausgesetzt, leicht zu verwenden.
Die einzige schwierigere Hrde kann es sein, Pythons
Garbage-Collector Mechanismus (reference counting) richtig zu
verwenden.
Es zwar nicht wirklich schwierig, Erweiterungsmodule von Hand zu
schreiben, aber es ist deutlich mhseliger als 舍uivalenten
Python-Code zu schreiben, da z.B. Reference-Counting und
Fehlerbehandlung explizit implementiert werden mssen. Um sich
etwas Arbeit zu sparen, kann man in manchen F舁len diesen Code
auch generieren lassen. ワbliche Werkzeuge dazu sind u.a. SWIG (Simplified Wrapper and
Interface Generator) mit dem Schwerpunkt auf die Anbindung von
C- und C++-Bibliotheken and diverse Interpreter, darunter
Python, Perl und Tcl, sowie das neuere Pyrex
das mit einer Python-臧nlichen Sprache Erweiterungsmodule fr
Python erstellt.
Python Bibliotheken
Standardbibliothek
Eine St舐ke von Python, unabh舅gig von der eigenlichen Sprache,
ist die umfangreiche Standardbibliothek. Sie enth舁t Module fr
XML, Sockets, Internetprotokolle (http, ftp, xmlrpc, smtp, pop,
nntp, u.a.), Parser/Converter fr diverse (internet-)
Datenformate u.a. fr Emails (MIME, RFC822, einige Mailbox
formate), base64, hex, quoted printable.
GUI Toolkits
Es gibt Anbindungen von Python an eine ganze Reihe verschiedener
GUI-Toolkits. Hier wollen wir vor allem diejenigen vorstellen,
die fr Freie Software am wichtigsten sind, n舂lich Tkinter,
PyGTK und gnome-python, PyQT und PyKDE sowie wxPython.
Tkinter
Tkinter ist die Anbindung an Tk. Der Hauptvorteil von Tkinter
ist, da゚ es bestandteil der Standardbibliothek ist. Als
Entwickler kann man also davon ausgehen, da゚ es entweder
bereits beim Benutzer installiert (es ist zum Beispiel
Standardbestandteil des Windows Installers von Python) oder es
nicht schwer fr den Benutzer ist, es nachtr臠lich zu
installieren (die meisten GNU/Linux-Distributionen enthalten
ein Tkinter-paket).
Tkinter ist au゚erdem sehr stabil. Wenn ein Programm Tkinter
nicht richtig benutzt, gibt es praktisch immer eine
Python-Exception. Speicherzugriffsfehler und 臧nliche Probleme
sind extrem selten.
Das Angebot an GUI-Elementen, das Tkinter mitbringt ist aus
heutiger Sicht etwas mager, so gibt es z.B. kein "Tree-View"
fr die Darstellung von Baumstrukturen. Es gibt aber
Bibliotheken die solche Elemente in Python implementieren,
z.B. PMW.
Was von manchen als Nachteil empfunden wird, ist, da゚ Tkinter
nicht nur an Tk selbst gebunden ist, sondern dazu einen
kompletten Tcl-Interpreter verwendet. Sie sehen Tkinter daher
als aufgebl臧t und langsam an. Wir knen das so nicht
nachvollziehen. Sketch, zum Beispiel, das es momentan in
vergleichbarer Funktionalit舩 sowohl in einer Tkinter- als
auch einer PyGTK-Variante gibt, braucht mit GTK 2.2 deutlich
mehr Speicher als mit Tk. Beide Versionen fhlen sich
subjektiv auch etwa gleich schnell an.
wxPython
wxPython ist die Anbindung an wxWindows. wxWindows ist eine
plattformunabh舅gige GUI Bibliothek die auf den normalen
plattformspezifischen Bibliotheken aufsetzt und damit jeweils
ein zur Plattform gehendes Look&Feel hat.
wxWindows bietet einerseits Standardelemente wie Mens,
Dialoge, Buttons, etc. und auch komplexere Widgets wie etwa
das Grid-Widget fr Tabellen. wxWindows bietet darber hinaus
aber auch ein Applicationframework und plattformunabh舅gige
Schnittstellen fr Dinge, die nicht unmittelbar mit grafischen
Benutzeroberfl臘hen zu tun haben, wie etwa Drucken oder das
Starten von Subprozessen.
PyGTK und gnome-python
PyGTK ist die Anbindung an GTK+. Es ist Teil von gnome-python,
der Anbindung an die Gnome-Bibliotheken. GTK selbst ist im
wesentlichen nur ein Toolkit, d.h. es besteht aus den normalen
GUI-Elementen sowie einigen Standarddialogen. Drucken und
andere darber hinausgehende Dienste knen ber gnome-python
genutzt werden.
Zu den von pygtk untersttzten Plattformen geht neben
GNU/Linux und anderen Unix-臧nlichen Systemen auch MS Windows.
PyQt und PyKDE
PyQt und PyKDE sind, wie die Namen schon vermuten lassen, die
Anbindungen and Qt und KDE. トhnlich wie wxWindows bietet auch
Qt die Mlichkeit zum Drucken und andere Features, die nicht
direkt an die GUI gebunden sind.
Ein Nachteil von Qt gegenber den anderen hier erw臧nten
Toolkits ist, da゚ es nur in der Version fr das X Window
System Freie Software ist. Insbesondere ist die Version fr MS
Windows nicht frei. PyQt folgt im wesentlichen dem gleichen
Lizenzmodell wie Qt und ist nur fr die GPL-Version von Qt
Freie Software
Auswahl der "richtigen" Bibliothek
Welche der vielen Bibliotheken fr graphische
Benutzeroberfl臘hen, die mit Python genutzt werden knen, man
verwenden sollte h舅gt natrlich immer vom Projekt ab. Daher
knen wir hier nur recht allgemeine Hinweise geben.
Ein Applikation-Framework ist fr ein Python-Programm nicht
unbedingt wichtig. Viele Teile eines Applikation-Frameworks,
wie zum Beispiel Klassen um das Model-View-Controller-Konzept
zu implementieren sind in Python recht einfach selbst zu
schreiben (s.u.).
Schnittstellen zu nicht-GUI Funktionalit舩en wie etwa
Datenbanken sind in der Regel schon unabh舅gig von
GUI-Toolkits fr Python verfgbar und spielen daher aus der
Sicht eines Pythonprogrammierers eigentlich keine Rolle.
wxPython zum Beispiel verzichtet daher auch auf eine Anbindung
der Datenbankschnittstelle wxODBC.
Eine Ausnahme bildet hier das Drucken, da man zumindest unter
Windows dem Benutzer die Standarddialoge zur Druckerauswahl
und -konfiguration anbieten sollte. In dieser Hinsicht sind
wxWindows und Qt interessant.
Entwicklungsstrategien fr Python GUI-Programme
Trennen von Oberfl臘he und Applikation
Die wichtigste Strategie bei der Entwicklung von GUI
Applikationen im Allgemeinen ist eine weitgehende Trennung der
eigentlichen grafischen Benutzeroberfl臘he von der
Applikationslogik.
Diese Trennung ist in gewisser Weise eigentlich nur ein
Spezialfall einer grundlegenderen Strategie, n舂lich die
Kopplung zwischen verschiedenen Teilen eines Softwaresystems so
lose wie mlich zu gestalten.
Vorteile einer solchen Trennung:
-
Konzentration der Logik an einer Stelle
-
Einfacheres Testen
Dialoge und andere GUI-Elemente lassen sich meist nur schwer
automatisch testen. Wenn die GUI von der Applikationslogik
gut getrennt ist und damit die GUI-Schicht sehr dnn l舖st
sich ein Gro゚teil der Applikation automatisch testen.
-
Einfacherer Wechsel des GUI Toolkits
Ein Wechsel des Toolkits ist zwar sicherlich ein eher
seltenes Ereignis im Leben eines Programms, aber auch nicht
so selten.
Sketch zum Beispiel verwendete am Anfang eine
Pythonanbindung an Xt (die X-Toolkit Intrisics) und die
Athena Widgets und wechselte nach einer Weile zu Tkinter,
das in der stabilen Version immer noch verwendet wird. Die
Entwicklerversion verwendet mittlerweile GTK2. Bei der
Portierung war eine noch weitergehende Trennung von GUI und
Logik ein sehr wichtiger Schritt.
Model-View-Controller
Das Model-View-Controller (MVC) Konzept und seine Geschwister
Model-View-Presenter und die Observer Design-Pattern sind wohl
die bekanntesten Konzepte bei der Trennung von GUI und Logik.
Die Observer-Pattern ist allerdings nicht unbedingt auf GUIs
bezogen.
Die Kernidee hinter MVC ist, da゚ die Logik im Modell
implementiert ist, der View lediglich den Zustand (eines
Teils) des Modells darstellt und der Controller
Benutzereingaben wie z.B. Mausclicks entgegennimmt und in
Aufrufe von Methoden des Modells umsetzt.
In Thuban zum Beispiel ist das Modell die Karte mit den
verschiedenen Ebenen von Daten. Es gibt mehrere Views, unter
anderem die Karte im Hauptfenster und die Legende:
Der Ma゚stab unten links ist natrlich auch ein View, aber
nicht auf die Karte selbst, sondern auf den Skalierungsfaktor
der bei der Darstellung der Karte im rechten Teil des Fensters
verwendet wird. In einem Programm gibt es also meist nicht nur
ein Modell sondern mehrere und Views knen selbst wieder
Modelle sein.
Das Modell muss dabei natrlich die Views immer dann
informieren, wenn sich sein Zustand 舅dert, so da゚ sich die
Views auf den neuesten Stand bringen knen. Um die Kopplung
zwischen Modell und View lose zu halten, sollte das Modell
aber nicht wissen mssen, welche Views dies sind. In Sketch
und Thuban wird diese lose Kopplung durch einen in Python
implementierten Benachrichtigungsmechanismus erreicht.
Das Konzept hinter diesem Benachrichtigungsmechanismus ist,
da゚ es meist einige Objekte gibt, die Nachrichten senden und
viele Empf舅ger solcher Nachrichten. Die Sender sind
normalerweise von einer gemeinsamen Basisklasse,
Publisher abgeleitet.
Publisher-Instanzen verfentlichen
gewissermassen Nachrichten und die Empf舅ger abonnieren sie
indem sie mit den Methoden Subscribe und
Unsubscribe ihr Abo verwalten. Eine
Publisherinstanz verschickt nachrichten ber ihre
issue Methode.
Als Beispiel hier eine Methode aus Thubans
Map Klasse. Ein Kartenobjekt hat in Thuban
ein Projektion, durch die definiert ist, wie die Oberfl臘he
der Erde auf eine Ebene abgebildet wird. Die
SetProjection Methode weist eine neue
Projektion zu:
def SetProjection(self, projection):
self.projection = projection
self.issue(MAP_PROJECTION_CHANGED, self)
|
Hier wird also zun臘hst einfach die Projektion an die
entsprechende Instanzvariable gebunden und dann eine
MAP_PROJECTION_CHANGED Nachricht
verschickt. Die Nachricht hat einen Parameter, n舂lich die
Karte selbst so da゚ Empf舅ger Nachrichten von verschiedenen
Karten auseinanderhalten knen.
Fr die Empf舅gerseite hier ein Beispiel aus der View-Klasse:
def SetMap(self, map):
if self.map is not None:
self.map.Unsubscribe(MAP_PROJECTION_CHANGED,
self.projection_changed)
self.map = map
if self.map is not None:
self.map.Subscribe(MAP_PROJECTION_CHANGED,
self.projection_changed)
|
Die SetMap Methode weist dem View eine neu
darzustellende Karte zu. Zuerst mu゚ also die Benachrichtigung
bei der eventuell vorhandenen alten Karte abbestellt werden
(mit Unsubscribe) und nachdem die
Instanzvariable gesetzt wurde wird die Nachricht der neuen
Karte abonniert. Der Code hier ist recht stark vereinfacht, da
es unter anderem noch einige andere Nachrichten gibt, auf die
der View reagieren sollte.
Der erste Parameter von Subscribe und
Unsubscribe ist der Nachrichtentyp. Der
zweite ein aufrufbares Objekt -- hier eine gebundene Methode.
Wenn eine Nachricht gesendet wird, wird das aufrufbare Objekt
mit den Parametern der Nachricht aufgerufen.
Fr (noch) nicht Pythonprogrammierer bedarf der Begriff
"gebunden Methode" vielleicht noch einer Erl舫terung. Ein
Methodenaufruf sieht in Python sehr 臧nlich aus wie in Java
oder C++:
objekt.methode(arg1, arg2)
|
Bei der Ausfhrung dieses Methodenaufrufs wertet Python
zun臘hst den Ausdruck objekt.methode aus.
Das liefert, wenn "methode" tats臘hlich der
Name einer Methode des Objekts objekt ist,
ein gebundenes Methodenobjekt. Ein solches Objekt enth舁t eine
Referenz auf das Objekt, an das es gebunden ist, und eine
Referenz auf das Funktionsobjekt, das die Methode
implementiert. Beim Aufruf des Methodenobjekts wird dann die
Funktion mit dem Objekt als erstem Parameter aufgerufen.
In unserem Fall ist die Methode folgende:
def projection_changed(self, *args):
self.FitMapToWindow()
|
Das, hei゚t, wir ignorieren alle Argumente
(args, ein Tuple das alle Parameter der
Methode bis auf self enth舁t, wird in der Methode nirgends
mehr verwendet) und passen dann die Skalierung der
Kartendarstellung so an, da゚ die ganze Karte ins Fenster
passt. FitMapToWindow sorgt auch dafr, da゚
die Karte neu gezeichnet wird.
Nun kann es sehr leicht passieren, da゚ durch eine
Benutzeraktion mehrere Nachrichten vom Modell verschickt
werden, die alle ein Update des Fensters verlangen. Wenn das
Neuzeichnen sehr aufw舅dig ist, wie hier im Falle von Thuban,
wo hinter einer Karte viele Megabytes an Daten stehen knen,
ist es wichtig, das Zeichnen etwas aufzuschieben, bis das
Programm wieder auf Ereignisse des Fenstersystems wartet. Die
meisten Toolkits bieten hierfr sogenannt Idle-Events an.
Undo
Gute Anwendungen sollten den Benutzer nach Mlichkeit davor
bewahren, nicht zu behebende Fehler zu machen. Eine der aus
Anwender angenehmsten Lungen ist es, zu Erlauben, トnderungen
rckgangig zu machen.
Bei der Implementation der Undo-Funktionalit舩 muss fr jede
Benutzeraktion festgehalten werden, was sich am Dokument in
welcher Weise 舅dert, um beim Zurcknehmen der トnderungen den
vorherigen Zustand wieder herstellen zu knen. Was das
"Dokument" ist h舅gt von der Art des Programms ab. In einer
Tabellenkalkulation ist es z.B. eine Sammlung von Tabellen
Wir wollen uns nun anschauen, wie Sketch dieses Problem lt.
Das Dokument in Sketch ist eine ganze Vektorzeichnung. Die
Zeichnung besteht aus bereinander gezeichneten Ebenen die
wiederum aus verschiedenen Arten von Objekten bestehen. Die
Objekte knen Text, Rastergraphiken, Linien, und so weiter
sein, aber auch Gruppen die wiederum solche Objekte enthalten.
Darunter knen auch Objekte sein, die nicht direkt Teil von
Sketch sind, weil sie durch Plugins implementiert werden.
Sketch mu゚ nun in der Lage sein, トnderungen an all diesen
Objekten festzuhalten und rckgangig machen zu knen.
Der Lungsansatz besteht darin, die Objekte selbst dafr sorgen
zu lassen da゚ die richtige Undo-Informationen vorhanden sind.
Das geschieht in Sketch dadurch, da゚ Methoden, die die Objekte
ver舅dern diese Informationen zurckgeben.
Als Beispiel hier eine Methode aus einem Plugin-Objekt das
regelm舖sige Vielecke implementiert. Dies Objekte besitzen einen
Radius (mathematisch betrachtet der Radius des Umkreises) den
der Benutzer definieren kann. Dabei wird die
SetRadius-Methode aufgerufen:
def SetRadius(self, radius):
# undoinfo erzeugen
undo = self.SetRadius, self.radius
# Instanzvariable setzen
self.radius = radius
# interne Datenstrukturen updaten...
# undoinfo an den Aufrufer zurckgeben.
return undo
|
Die Undo-Informationen, in Sketch meist einfach Undoinfo
genannt, ist einfach ein Tupel aus einem aufrufbaren Objekt,
gefolgt von eventuellen Parametern. Das aufrufbare Objekt ist
hier wieder eine gebundene Methode. Die Radius舅derung
zurckzunehmen bedeutet, wieder den alten Radius zu setzen, also
verwenden wir die SetRadius-Methode selbst
und den alten Radius als parameter.
Der Aufrufer wird in der Regel die Undoinfo Objekte die er
bekommt in einem neuen Undoinfo-Objekt zusammenfassen und an
seinen Aufrufer bergeben. Eine Ausnahme bilden die Funktionen,
die Benutzeraktionen implementieren. An diesen Stellen wird das
Undoinfo Objekt an das Dokument bergeben.
Wenn die Aktion, die durch ein Undoinfo-Objekt repr舖entiert
wird, zurckgenommen wird, wird einfach das aufrufbare Objekt
mit den Parametern aufgerufen.
Wenn man sich das Beispiel genauer anschaut, erkennt man, da゚
hier beim Ausfhren des Undo wieder ein Undoinfo-Objekt erzeugt
wird. Diesesmal kann man es verwenden, um das Undo selbst
rckg舅gig zu machen, man kann es also fr das "Redo" verwenden.
Daher ist es in Sketch eine Auflage fr das aufrufbare Objekt im
Undoinfo-Objekt, beim Aufruf wiederumg ein Undoinfo-Objekt
zurckzugeben.
Ein Nachteil dieses Konzepts ist, da゚ der Aufrufer fr die
richtige Behandlung der Undoinfo-Objekte verantwortlich ist.
Besser w舐e es wahrscheinlich, wenn die Objekte selbst die
Undoinfo-Objekte an das Dokument bergeben. In Sketch w舐e das
in jedenfalls kein gro゚es Problem, da die meisten Objekte eine
Referenz auf das Dokumentobjekt besitzen, zu dem sie gehen.
Schlu゚bemerkungen
Es gibt noch viele andere Beispiele aus Sketch oder Thuban, die
die Verwendung von Python fr GUI-Porgramme demonstrieren knen:
-
Plugins, um Applikationen durch Zusatzmodule zu
erweitern
-
Benutzerdefinierte Pythonskripte
In einem Programm, das selbst in Python geschrieben ist, haben
die solche Skripte automatisch Zugriff auf alle interessanten
Objekte des Programms, so da゚ ein sehr leistungsf臧iges
Skriptinterface mit wenig Aufwand implementiert werden kann.
Auf diese Mlichkeiten auch noch einzugehen, wrde den Rahmen des
Vortrags sprengen, aber da sowohl Thuban als auch Sketch Freie
Software sind, knen Sie natrlich in den Quelltext schauen und
daraus fr ihre eigenen Programme lernen.
|
![](/file/22360/VPR0403.ISO/gfx/pixel.gif) |
|