[LTNet]OPEN-EVENTS::OPEN MUSIC::MINICONTENT::KNOPPIX LINUXTAG.org
Cornerstone
// 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.
EUROPAS GRヨSSTE GNU/LINUX MESSE UND KONFERENZ
KONFERENZ-CD-ROM 2003
Hauptseite Vortr臠e Bcher History Software Knoppix Sponsoren Abspann Impressum
Hauptseite//Vortr臠e//Python als Basis fr komplexe GUI Anwendungen

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 Mlichkeit, 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 knen.

Thuban ist ein Anwendung zum Betrachten von geographischen Daten. Die Daten knen 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 mlichen Fehler eines Programms finden knen und man daher auch in statisch typisierten Sprachen nicht auf (mlichst 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 ermlichen 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 ermlichen es, im gleichen Zeitraum eine grere Zahl verschiedener Algorithmen und Datenstrukturen fr die Lung eines Problems auszuprobieren, so da゚ man h舫fig zu einer besseren Lung gelangt, als mit C oder C++ im gleichen Zeitraum mlich 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 ermlicht 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 mlich, 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 knen 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 gehendes 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 knen ber gnome-python genutzt werden.

Zu den von pygtk untersttzten Plattformen geht 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 Mlichkeit 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 knen, man verwenden sollte h舅gt natrlich immer vom Projekt ab. Daher knen 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 mlich 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 knen 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 knen. 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 verfentlichen 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 knen.

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 knen, 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 Mlichkeit davor bewahren, nicht zu behebende Fehler zu machen. Eine der aus Anwender angenehmsten Lungen 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 knen. 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 lt. 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 knen Text, Rastergraphiken, Linien, und so weiter sein, aber auch Gruppen die wiederum solche Objekte enthalten. Darunter knen 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 knen.

Der Lungsansatz 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 gehen.

Schlu゚bemerkungen

Es gibt noch viele andere Beispiele aus Sketch oder Thuban, die die Verwendung von Python fr GUI-Porgramme demonstrieren knen:

  • 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 Mlichkeiten auch noch einzugehen, wrde den Rahmen des Vortrags sprengen, aber da sowohl Thuban als auch Sketch Freie Software sind, knen Sie natrlich in den Quelltext schauen und daraus fr ihre eigenen Programme lernen.

Impressum // ゥ 2003 LinuxTag e.V.