Ampel
Das Ampel-Beispiel zeigt, wie man Qt State Machine Overview verwendet, um den Kontrollfluss einer Ampel zu implementieren.
In diesem Beispiel schreiben wir eine TrafficLightWidget-Klasse. Die Ampel hat drei Ampeln: Rot, Gelb und Grün. Die Ampel wechselt in bestimmten Intervallen von einer Ampel zur anderen (rot zu gelb zu grün zu gelb zu wieder rot).
class LightWidget : public QWidget { Q_OBJECT Q_PROPERTY(bool on READ isOn WRITE setOn) public: explicit LightWidget(const QColor &color, QWidget *parent = nullptr) : QWidget(parent), m_color(color) { } bool isOn() const { return m_on; } void setOn(bool on) { if (on == m_on) return; m_on = on; update(); } public slots: void turnOff() { setOn(false); } void turnOn() { setOn(true); } protected: void paintEvent(QPaintEvent *) override { if (!m_on) return; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(m_color); painter.drawEllipse(rect()); } private: QColor m_color; bool m_on = false; };
Die LightWidget-Klasse repräsentiert eine einzelne Ampel. Sie bietet eine Eigenschaft on
und zwei Slots, turnOn() und turnOff(), um die Ampel an- bzw. auszuschalten. Das Widget färbt sich in der Farbe, die dem Konstruktor übergeben wird.
class TrafficLightWidget : public QWidget { Q_OBJECT public: explicit TrafficLightWidget(QWidget *parent = nullptr) : QWidget(parent) { auto vbox = new QVBoxLayout(this); m_red = new LightWidget(Qt::red); vbox->addWidget(m_red); m_yellow = new LightWidget(Qt::yellow); vbox->addWidget(m_yellow); m_green = new LightWidget(Qt::green); vbox->addWidget(m_green); auto pal = palette(); pal.setColor(QPalette::Window, Qt::black); setPalette(pal); setAutoFillBackground(true); } LightWidget *redLight() const { return m_red; } LightWidget *yellowLight() const { return m_yellow; } LightWidget *greenLight() const { return m_green; } private: LightWidget *m_red; LightWidget *m_yellow; LightWidget *m_green; };
Die Klasse TrafficLightWidget stellt den visuellen Teil der Ampel dar; es ist ein Widget, das drei vertikal angeordnete Lichter enthält und Zugriffsfunktionen für diese bereitstellt.
QState *createLightState(LightWidget *light, int duration, QState *parent = nullptr) { auto lightState = new QState(parent); auto timer = new QTimer(lightState); timer->setInterval(duration); timer->setSingleShot(true); auto timing = new QState(lightState); QObject::connect(timing, &QAbstractState::entered, light, &LightWidget::turnOn); QObject::connect(timing, &QAbstractState::entered, timer, QOverload<>::of(&QTimer::start)); QObject::connect(timing, &QAbstractState::exited, light, &LightWidget::turnOff); auto done = new QFinalState(lightState); timing->addTransition(timer, &QTimer::timeout, done); lightState->setInitialState(timing); return lightState; }
Die Funktion createLightState() erzeugt einen Zustand, der eine Ampel anschaltet, wenn der Zustand betreten wird, und ausschaltet, wenn der Zustand wieder verlassen wird. Der Zustand verwendet einen Timer, und wie wir sehen werden, wird der Timeout für den Übergang von einem LightState zum anderen verwendet. Hier ist das Zustandsdiagramm für den Lichtzustand:
class TrafficLight : public QWidget { Q_OBJECT public: explicit TrafficLight(QWidget *parent = nullptr) : QWidget(parent) { auto vbox = new QVBoxLayout(this); auto widget = new TrafficLightWidget; vbox->addWidget(widget); vbox->setContentsMargins(QMargins()); auto machine = new QStateMachine(this); auto redGoingYellow = createLightState(widget->redLight(), 3000); redGoingYellow->setObjectName("redGoingYellow"); auto yellowGoingGreen = createLightState(widget->yellowLight(), 1000); yellowGoingGreen->setObjectName("yellowGoingGreen"); redGoingYellow->addTransition(redGoingYellow, &QState::finished, yellowGoingGreen); auto greenGoingYellow = createLightState(widget->greenLight(), 3000); greenGoingYellow->setObjectName("greenGoingYellow"); yellowGoingGreen->addTransition(yellowGoingGreen, &QState::finished, greenGoingYellow); auto yellowGoingRed = createLightState(widget->yellowLight(), 1000); yellowGoingRed->setObjectName("yellowGoingRed"); greenGoingYellow->addTransition(greenGoingYellow, &QState::finished, yellowGoingRed); yellowGoingRed->addTransition(yellowGoingRed, &QState::finished, redGoingYellow); machine->addState(redGoingYellow); machine->addState(yellowGoingGreen); machine->addState(greenGoingYellow); machine->addState(yellowGoingRed); machine->setInitialState(redGoingYellow); machine->start(); } };
Die TrafficLight-Klasse kombiniert das TrafficLightWidget mit einem Zustandsautomaten. Der Zustandsgraph hat vier Zustände: rot-zu-gelb, gelb-zu-grün, grün-zu-gelb und gelb-rot. Der Anfangszustand ist rot-gelb; wenn der Zeitgeber des Zustands abläuft, geht der Zustandsautomat in gelb-grün über. Derselbe Prozess wiederholt sich bei den anderen Zuständen. So sieht das Zustandsdiagramm aus:
int main(int argc, char **argv) { QApplication app(argc, argv); TrafficLight widget; widget.resize(110, 300); widget.show(); return app.exec(); }
Die Funktion main() konstruiert eine Ampel und zeigt sie an.
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.