交通信号
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を構築し、それを表示する。
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。