信号機
「信号機」の例では、Qt State Machine の概要を活用して、信号機の制御フローを実装する方法を示します。

この例では、TrafficLightWidget クラスを作成します。この信号機には、赤、黄、緑の3つの信号があります。信号機は、一定の間隔で次の信号へと切り替わります(赤→黄→緑→黄→再び赤)。
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クラスは、信号機の1つのランプを表します。このクラスは、on プロパティと、ランプの点灯・消灯を行う2つのスロット(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クラスは、信号機の視覚的な部分を表します。これは、3つの信号灯が縦に配置されたウィジェットであり、これらにアクセスするためのアクセサ関数を提供します。
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 から別の 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とステートマシンを組み合わせたものです。ステートグラフには、赤→黄、黄→緑、緑→黄、黄→赤の4つの状態があります。 初期状態は「赤→黄」です。この状態のタイマーがタイムアウトすると、ステートマシンは「黄→緑」の状態に移行します。他の状態についても同様のプロセスが繰り返されます。ステートチャートは次のようになります:

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.