UML-Zustandsdiagramme mit PlantUML erstellen
https://oer-informatik.de/uml-zustandsdiagramm-plantuml
PlantUML, UML, Zustandsdiagramm, Diagramm als Code, Transition, Choice, Junction, Historie, Regionen, skinparam
https://bildung.social/@oerinformatik/
tl/dr; (ca. 16 min Lesezeit): Mithilfe des Tools PlantUML lassen sich textbasiert UML-Zustandsdiagramme erstellen. Der Artikel zeigt die Syntax für Zustände, Transitionen, innere Aktionen, Choices und Junctions, zusammengesetzte Zustände, Regionen und Historie sowie Möglichkeiten, die Diagramme zu teilen und einheitlich zu formatieren [AI-Assisted]. (Zuletzt geändert am 11.11.2026)
Dieser Artikel ist Teil einer Artikelreihe über UML-Diagramme: Klassendiagramm / Sequenzdiagramm / Aktivitätsdiagramm / Zustandsdiagramm (State) / Anwendungsfall-Diagramm (Use Case). Für alle sind jeweils auch PlantUML-Anleitungen verlinkt.
Hintergrundinformationen finden sich in diesem Grundlagenartikel zum UML-Zustandsdiagramm, Übungen unter Übungsaufgaben zum UML-Zustandsdiagramm.
Schon fit in diesem Thema? Nutze die Kann-Liste und die Leitfragen unter dem Artikel als Checkliste, ob Du die relevanten Kompetenzen bereits hast.
Als PlantUML-Grundlagen für Zustandsdiagramme kann ich nach Durchlesen des Artikels…
… Zustände (auch mit Alias) deklarieren und Start- und Endzustand mit
[*]notieren,… Transitionen mit Trigger, Guard und Effekt beschriften und die Pfeilrichtung (
-right->,-down->…) steuern,… innere Aktionen (
entry,do,exit) und innere Transitionen in Zuständen notieren,… dynamische Verzweigungen mit
<<choice>>einbinden und statische Verzweigungen (junctions) als Einzeltransitionen modellieren,… zusammengesetzte Zustände mit geschweiften Klammern und Regionen mit
--anlegen.
Darüber hinaus kann ich als PlantUML-Expertenwissen…
… flache und tiefe Historie (
[H],[H*]) notieren und fehlende Notationselemente wie den Terminator per Sprite nachbilden,… Diagramme über den PlantUML-Webservice teilen und per
skinparamoder eingebundener Konfigurationsdatei einheitlich formatieren.
Die wichtigsten PlantUML-Bausteine für Zustandsdiagramme im Überblick:
PlantUML ist ein vielseitig nutzbares Tool, um textbasiert versionierbare (UML-)Diagramme zu erstellen. Aus einfachen Quelltexten lassen sich so UML-Diagramme als PNG, ASCII-Art oder SVG erstellen. PlantUML ist als Webservice verfügbar (z. B. planttext.com), in vielen IDEs (als Plugin) integriert und wird von einigen Markdown-Interpretern direkt umgewandelt. Allgemeine weitere Infos zu PlantUML-Zustandsdiagrammen finden sich in der offiziellen Dokumentation.
Da die Anleitungen zu UML-Diagrammen nicht immer den aktuellen UML-Standard im Blick haben, versuche ich hier praktische Tipps zu geben, wie standardkonforme UML-Zustandsdiagramme mit PlantUML erstellt werden können.
Grundbausteine des UML-Zustandsdiagramms
UML-Zustandsdiagramme bestehen im Wesentlichen aus einem Startzustand, einzelnen Zuständen, einem Endzustand (optional) sowie Transitionen, die die Zustände verbinden. In PlantUML werden Zustände zunächst deklariert (state Zustand1 oder bei längerem Namen mit Alias state "Dargestellter Name des \nZustands 2" as Zustand2) und die verbindenden Transitionen in Zeilen mit stilisiertem ASCII-Pfeil beschrieben:
state hungrig
state "satt" as wohlgenährt
hungrig -> wohlgenährt
Start- und Endzustand werden in PlantUML mit [*] notiert. Anhand der Pfeilrichtung wird automatisch erkannt, ob es sich um einen Start- oder einen Endzustand handelt:
left to right direction
[*] --> Zustand1
Zustand1 --> [*]
Transitionen
An den Transitionen können - wie in der UML üblich - Event (Trigger), Guard (Bedingung) und Effekt (Aktion während der Transition) notiert werden (in der Form: startzustand -> zielzustand: Trigger [Guard] / Effekt). In PlantUML sieht es wie folgt aus:
state hungrig
state satt
hungrig -right-> satt : essen [wenn Essen da] /schmatzen()
Innere Aktionen der Zustände
Die Zustände können mit inneren Aktionen versehen werden, sie werden mit Hilfe des Zustandsnamens und folgendem Doppelpunkt notiert - entweder nach dem Muster
Event [Guard] / interneAktion
oder entsprechend der drei internen Events: entry, do, exit:
state schlafend
schlafend : entry/Augen zu
schlafend : do/träumen
schlafend : exit/Augen auf
schlafend : Vollmond [Werwolf == true]/Schlafwandeln
state wach
wach : entry/Kaffee trinken
wach : do/arbeiten
wach : exit/Zähneputzen
wach -right-> schlafend : [Müdigkeit > Wille] /Schlafanzug anziehen
schlafend -left-> wach : Weckerklingeln [zeit>=weckzeit] /aufstehen
schlafend -left-> schlafend : aufschrecken [zeit<weckzeit] /weiterschlafen
Verzweigungen (Choices)
Um dynamische Entscheidungen (Choices) in PlantUML einzubinden, muss die Raute als Pseudozustand mit dem Stereotyp <<choice>> deklariert werden und danach wie jeder andere Zustand eingebunden werden:
state State1: entry/a=1
state entscheidung <<choice>>
state State2
state State3
State1 -> entscheidung : trigger /a++
entscheidung -> State2 :[a == 1]
entscheidung -> State3 :[else]
Wichtig: bei Choices wird der Guard erst nach dem Effekt ausgewertet. In folgendem Beispiel wird a (in State1: a = 1) also erst hochgezählt (a++, also a=2) und dann der Guard ausgewertet ((a == 1) = false) - es wird also immer die [else]-Transition genommen und State3 erreicht.
Kreuzungen (Junctions)
Sofern die Guards bereits vor den Effekten ausgewertet werden sollen (statische Entscheidungen / junctions), können die Transitionen im UML-Diagramm über einen junction-Knoten (kleiner ausgefüllter Kreis) zusammengefasst werden. Ein eigenes Element dafür kennt PlantUML nicht. Da eine junction nur eine Kurzschreibweise ist, werden diese zusammenhängenden Transitionen in PlantUML als einzelne Transitionen mit identischem Trigger und unterschiedlichen Guards modelliert:
state State1
State1 : entry/ a=1
state State2
state State3
State1 -right-> State2 : trigger[a == 1]/a++
State1 --right-> State3 :trigger[a != 1]/a++
Der vordefinierte guard [else] ist in der UML nur an den ausgehenden Transitionen einer junction oder choice erlaubt. Bei den aufgelösten Einzeltransitionen steht deshalb die ausdrücklich verneinte Bedingung [a != 1].
Zusammengesetzte Zustände (composite states)
Mithilfe von geschweiften Klammern können zusammengesetzte Zustände (composite states) beliebig verschachtelt werden:
state schlafend
state wach{
state hungrig
state satt
hungrig -> satt : gegessen
satt -> hungrig : verdaut
}
schlafend -> wach : Wecker
wach -> schlafend : einschlafen
Sollen zusammengesetzte Zustände nur als Verweis dargestellt werden (die Unterzustände stehen dann in einem eigenen Diagramm), muss man mit PlantUML allerdings etwas zaubern, um das Symbol, das zwei Zustände zeigt, in die Ecke zu schreiben (Workaround: Tab (Unicode #9) zur Einrückung und Unendlich-Symbol (Unicode #8734) zur Darstellung der Unterzustände):
@startuml
state "zusammengesetzter\nZustand" as subState
subState: 				<b>∞</b>
@enduml
Regionen in zusammengesetzten Zuständen
Mithilfe von zwei Bindestrichen lassen sich Regionen mit Unterzuständen definieren.
@startuml
left to right direction
state wach {
[*] --> zufrieden
zufrieden --> unzufrieden : Sonne
unzufrieden --> zufrieden : Regen
--
[*] --> neugierig
neugierig --> gelangweilt : warten
gelangweilt --> neugierig : loslegen
}
@enduml
Historie und Terminator
Die Historie (history) eines zusammengesetzten Zustands kennt PlantUML inzwischen direkt (getestet mit Version 1.2026.8): Als Ziel einer Transition notierst Du wach[H] für die flache und wach[H*] für die tiefe Historie. Alternativ lässt sich der Pseudozustand innerhalb des zusammengesetzten Zustands mit state h <<history>> bzw. <<history*>> deklarieren. Führt vom H-Knoten keine eigene Transition weg, wird beim ersten Betreten der Startzustand der Region eingenommen.
state wach {
[*] --> hungrig
hungrig -right-> satt : gegessen
satt --> hungrig : verdaut
}
state schlafend
[*] --> wach
satt -right-> schlafend : einschlafen
schlafend -up-> wach[H] : Wecker
schlafend -right-> [*]
Mit wach[H*] als Ziel entsteht entsprechend die tiefe Historie; eine Standardtransition des H-Knotens notierst Du innerhalb des zusammengesetzten Zustands, z. B. [H*] --> hungrig:
Für den Terminator (X, beendet die gesamte Zustandsmaschine sofort) kennt PlantUML dagegen kein eigenes Element; <<end>> zeichnet einen Endzustand, kein Kreuz. Die Formatvorlage umlstate.cfg von oer-informatik.de (siehe Abschnitt „Aufhübschen“) bringt dafür den Sprite $terminate und die passende Stilklasse mit: Der Terminator wird als Zustand mit dem Stereotyp <<terminate>> notiert, dessen Name nur aus dem Sprite besteht. Rahmen, Füllung und Stereotyp blendet die cfg aus, sichtbar bleibt nur das Kreuz.
@startuml
!include https://uml-diagramme-d87af5.gitlab.io/plantuml/umlstate.cfg
left to right direction
skinparam lineType polyline
state wach {
[*] --> zufrieden
zufrieden --> unzufrieden : Sonne
unzufrieden --> zufrieden : Regen
--
[*] --> neugierig
neugierig --> gelangweilt : warten
gelangweilt --> neugierig : loslegen
state "<$terminate,color=DarkSlateBlue>" as ende <<terminate>>
gelangweilt --> ende : totlangweilen
}
@enduml
Geerbte Zustände
Auch Zustandsautomaten lassen sich spezialisieren: Zustände, die von der Eltern-Zustandsmaschine geerbt werden, werden mit gestrichelter Linie dargestellt – in PlantUML folgendermaßen:
@startuml
state geerbterZustand ##[dashed] {
}
@enduml
plantUML-Webservice zur Diagrammerzeugung nutzen
PlantUML bietet einen Webservice, der Diagramme unmittelbar online rendert.
Variante 1: Codierter Quelltext: PlantUML kodiert den Quelltext, um ihn so über den Webservice zugänglich (und bearbeitbar) zu machen. Die URL ist in diesem Fall wie folgt aufgebaut: https://www.plantuml.com/plantuml/AUSGABEFORMAT/CODIERTERQUELLTEXT wobei als AUSGABEFORMAT
png,svg,eps,epstextundtxtgenutzt werden kann. Wird als AUSGABEFORMATumlgewählt, erhält man den bearbeitbaren Quelltext.Variante 2: Editierbare Links lassen sich auch über den Service von planttext.com erstellen, sie nutzen dieselbe Quelltextcodierung und URLs nach dem Muster: https://www.planttext.com/?text=CODIERTERQUELLTEXT Auch in den erzeugten PNG-Dateien wird der codierte Quelltext als Titel hinterlegt, so dass sie sich relativ einfach später weiterverarbeiten lassen.
Variante 3: Quelltext direkt online rendern: der PlantUML-Quelltext ist online als Resource verfügbar und soll gerendert ausgegeben werden. Hierzu muss eine URL nach dem Muster: https://www.plantuml.com/plantuml/proxy?fmt=AUSGABEFORMAT&src=https://URL_PLANTUMLSOURCE erstellt werden, wobei als AUSGABEFORMAT
png,svg,eps,epstextundtxtgenutzt werden kann. Diese Funktion scheint derzeit deaktiviert zu sein oder nur Entwicklern vorbehalten.
plantUML-Formatierung: Aufhübschen von UML-Diagrammen
Über Skins bietet PlantUML die Möglichkeit, die Diagramme in Schriftart, Farben und Aussehen individuell anzupassen. Die Zustandsdiagramme dieser Artikelreihe tragen dafür keine eigenen skinparam-Zeilen, sondern binden die Formatvorlage (Hausnotation) von oer-informatik.de per !include ein:
@startuml
!include https://uml-diagramme-d87af5.gitlab.io/plantuml/umlstate.cfg
state hungrig
state satt
hungrig -right-> satt : essen [wenn Essen da] / schmatzen()
@enduml
Die Datei umlstate.cfg legt unter anderem fest:
skinparam style strictuml, Schatten und die Schrift „Lucida Sans Typewriter“,Zustände in
snowmit Rahmen inDarkSlateBlue, Rauten (choices) inghostwhite, Notizen inLightYellow, Pfeile inDarkSlateBlueund rechtwinklige Linien (lineType ortho),hide empty description(keine Trennlinie unter Zuständen ohne innere Aktionen) und abgerundete Ecken auch für zusammengesetzte Zustände (per<style>),den Sprite
$terminatefür den Terminator (siehe Abschnitt „Historie und Terminator“),eine Fußzeile, die jedes Diagramm mit Urheber und Artikel-URL versieht.
Eine eigene Zeile center footer … nach dem !include ersetzt die Fußzeile der cfg. Liegen Kantenbeschriftungen ungünstig, hilft im einzelnen Diagramm skinparam lineType polyline.
UML-Zustandsdiagramme per Formatierung als Entwurf kennzeichnen
Um den Entwurfscharakter eines Diagramms zu unterstützen, kann ein Layout verwendet werden, das Handschrift ähnelt. Besonders wirkungsvoll ist das, wenn auch die Schrift authentisch handschriftlich aussieht. Dies ist z. B. bei der Schriftart “FG Virgil” der Fall (diese muss aber auf dem System installiert sein). Welche Schriften das jeweilige System bietet, lässt sich mit dem PlantUML-Befehl listfonts anzeigen. Wichtig ist: sofern eine Vektorgrafik ausgegeben wird (svg, eps), muss die Schrift auf allen anzeigenden Computern vorhanden sein, andernfalls werden Ersatzschriftarten verwendet.
Die entsprechenden Skin-Parameter sind:
skinparam style strictuml
skinparam DefaultFontName "FG Virgil"
skinparam handwritten true
skinparam monochrome true
skinparam packageStyle rect
skinparam shadowing false
Das Ergebnis sieht dann etwa so aus:
Diagramme vereinheitlichen und Formatierung auslagern
Damit nicht alle PlantUML-Diagramme dieselben skinparam-Sequenzen am Beginn der PlantUML-Datei nennen müssen, kann eine zentrale Konfigurationsdatei eingebunden werden, die die Formatierungen enthält:
!include https://PATH.TO/MY/UMLSTATE_CONFIG.cfg
Alle Befehle in dieser Datei werden ausgeführt, als stünden sie in der umgebenden PlantUML-Datei. Um ein einheitliches Layout zu erreichen, ist diese Funktion sehr praktisch! Die Zustandsdiagramme dieser Artikelreihe binden auf diese Weise die oben beschriebene umlstate.cfg ein.
Leitfragen
- Wie deklarierst Du Zustände (auch mit Alias), Start- und Endzustand, und wie beschriftest Du Transitionen mit Trigger, Guard und Effekt?
Zustände deklarierst Du mit state name bzw. state "Langer Name" as alias, Start- und Endzustand notierst Du beide mit [*] – die Pfeilrichtung entscheidet ([*] --> a bzw. a --> [*]). Transitionen schreibst Du als a --> b : trigger [guard] / effekt, die Richtung steuerst Du mit -right->, -down-> usw.; siehe Abschnitt „Grundbausteine“ und Abschnitt „Transitionen“.
- Wie notierst Du innere Aktionen und innere Transitionen eines Zustands?
Nach dem Zustandsnamen und einem Doppelpunkt, je Zeile eine Aktion: schlafend : entry/Augen zu, schlafend : do/träumen, schlafend : exit/Augen auf und für innere Transitionen schlafend : Vollmond [Werwolf == true]/Schlafwandeln; siehe Abschnitt „Innere Aktionen der Zustände“.
- Wie bindest Du eine choice ein, und wie modellierst Du eine junction in PlantUML?
Die choice deklarierst Du als Pseudozustand state entscheidung <<choice>> und verbindest sie wie einen Zustand; ein Zweig erhält [else]. Für junctions gibt es kein eigenes Element, deshalb modellierst Du sie als einzelne Transitionen mit gleichem Trigger und unterschiedlichen Guards; siehe Abschnitt „Verzweigungen (Choices)“ und Abschnitt „Kreuzungen (Junctions)“.
- Wie legst Du zusammengesetzte Zustände, Regionen und die Historie an?
Unterzustände stehen in geschweiften Klammern (state wach { … }), Regionen trennst Du darin mit --, und jede Region bekommt einen eigenen Startzustand. Die Historie erreichst Du über das Ziel wach[H] (flach) bzw. wach[H*] (tief); siehe Abschnitt „Zusammengesetzte Zustände“, Abschnitt „Regionen“ und Abschnitt „Historie und Terminator“.
- Wie sorgst Du dafür, dass alle Diagramme einheitlich aussehen?
Die Formatierung (skinparam, Schrift, Farben) steht in einer zentralen Konfigurationsdatei, die jedes Diagramm per !include <URL> einbindet; siehe Abschnitt „Diagramme vereinheitlichen und Formatierung auslagern“.
Links und weitere Informationen
Es finden sich zahlreiche Quellen und Dokumentationen zu PlantUML im Netz, erwähnenswert sind u. a.:
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “UML-Zustandsdiagramme mit PlantUML erstellen” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/uml-zustandsdiagramm-plantuml veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/uml/uml-diagramme. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 11.11.2026.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
