信号機
Traffic Lightの例では、Qt State Machine Overviewを使って信号機の制御フローを実装する方法を示します。
この例では、TrafficLightWidgetクラスを記述します。信号機には3つのライトがあります:赤、黄、緑です。信号機は、ある間隔で1つの信号から別の信号(赤→黄→緑→黄→再び赤)に遷移します。
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を構築し、それを表示する。
© 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.