交通信号灯
“交通信号灯”示例展示了如何使用Qt State Machine 概述来实现交通信号灯的控制流。

在此示例中,我们将编写一个 TrafficLightWidget 类。该交通信号灯有三个灯:红灯、黄灯和绿灯。交通信号灯会以特定间隔在不同颜色之间切换(红→黄→绿→黄→红)。
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;
};LightWidget 类表示交通信号灯中的单个灯。它提供了一个名为 `on ` 的属性,以及两个插槽 `turnOn()` 和 `turnOff()`,分别用于打开和关闭该灯。该控件会根据传递给构造函数的颜色来绘制自身。
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;
};TrafficLightWidget 类代表交通信号灯的视觉部分;它是一个包含三个垂直排列的灯的小部件,并为这些灯提供了访问函数。
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;
}createLightState() 函数创建一个状态,当进入该状态时灯会亮起,当退出该状态时灯会熄灭。该状态使用了一个定时器,正如我们即将看到的,超时用于从一个 LightState 过渡到另一个。以下是交通信号灯状态图:

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();
}
};TrafficLight 类将 TrafficLightWidget 与状态机相结合。状态图包含四个状态:红转黄、黄转绿、绿转黄和黄转红。 初始状态为“红转黄”;当该状态的定时器超时后,状态机将过渡到“黄转绿”状态。其余状态也遵循同样的过程。状态图如下所示:

int main(int argc, char **argv)
{
QApplication app(argc, argv);
TrafficLight widget;
widget.resize(110, 300);
widget.show();
return app.exec();
}main() 函数会创建一个 TrafficLight 实例并将其显示出来。
© 2026 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.