8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

QtAdvent Calendar 2016

Day 20

Qt Creator 4.2 のSCXML Editorを使ってみる!

Last updated at Posted at 2016-12-20

こんにちは、Qt Advent Calendar 2016の20日目の記事です。

何を記事にするか迷っていた時にQt Creator 4.2がリリースされ、新機能としてSCXML Editorが追加されました。自分も仕事でよく状態遷移図を使用するのでQt SCXMLのリリースは興味があり記事にしてみました。

Qt SCXMLはState Chart XMLファイルから状態遷移図を作成し、Qt C ++およびQt Quickアプリケーションに埋め込むことができるQtの新しいモジュールです。

SCXML Editorを使用するには

Qt Creator の[ヘルプ]メニューの[プラグインについて]を選択して、Modeling-ScxmlEditorをチェックします。ScxmlEditorはディフォルトでチェックされていません。
Screenshot .png

State Chart XMLの追加

Qt Creatorの[ファイル]メニューから[ファイル/プロジェクトの新規作成]を選択してモデリングの状態遷移を選択します。
新しファイル.png

次に状態遷移名とパスを決定します。。
状態遷移名.png

State Chart XMLの編集

サイドバーにあるプロジェクト ブラウザからscxmlファイルをクリックしてSCXML Editorを開きます。

ステート要素の追加

Common Statesからステート要素を選択してメインウィンドウにドラック&ドロップします。
path4151.png

ステート間の接続方法

メインウィンドウに配置されたFinal以外のステート要素を選択すると上部にいくつかのアイコンが表示されます。[↗アイコン]をクリックして接続したいステート要素の上で右クリックします。そうするとステート要素間を接続することができます。
updateScxml1.png

ステート要素の作成と接続方法

先ほどと同様に、ステート要素を選択します。上部の[□アイコン]をクリックして適当なところで右クリックします。そうすると、新規Stateの作成とステート要素間の接続が同時に行われます。
updateScxml2.png

同様にFinal/Parallel/Historyもステート要素の作成と接続が同時に可能です。

サンプル プログラム

簡単なサンプルプログラムを書いてみました。

サンプルプログラムの動作

  • S1ボタンをクリックすると、S11 → S12 → S13の状態を繰り返し遷移します。
  • S2ボタンをクリックするとS2状態に遷移します。
  • S2状態に遷移している状態で、S1ボタンをクリックすると最後のS1状態に復元します。(ヒストリー機能)
  • S2状態に遷移している状態で、Exitボタンをクリックすると、サンプルプログラムが終了します。

testWidget.png

サンプル プログラムの状態遷移図

(statemachine.scxml / scxml name: LessonStateMachine)
StateMachine70.png

サンプルプログラムの説明

stateChartXML.proの補足

  • プロジェクト ファイルにQt SCXMLモジュールをリンク対象にするためQT +=scxmlを追記します。
  • 状態遷移図を追加します。Qt CreatorからState Chart XMLを追加した場合は自動で記述されます。 (STATECHARTS += statemachine.scxml)
  • 最後に、load(qscxmlc)を追加します。
    Qt SCXML コンパイラ(qscxmlc)はscxmlファイルを読み取り、SCXMLで定義された状態遷移を実装するためのC++のソースとヘッダーファイルを生成します。
stateChartXML.pro
QT     += core gui scxml
CONFIG += c++11

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = stateChartXML
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
        testsignal.cpp

HEADERS  += testsignal.h

FORMS    += testsignal.ui

STATECHARTS += \
    statemachine.scxml

load(qscxmlc)

main.cppの補足

  • main.cppでLessonStateMachineのインスタンスを生成します。
  • LessonStateMachineクラスは、statemachine.scxmlで定義された状態遷移をQt SCXML コンパイラがビルドディレクトリに生成したstatemachine.cppとstatemachine.hに定義されています。

cpp/hのファイル名はscxmlファイル名から使用され、クラス名は状態遷移の名前(scxml name)が使用されるようです。

main.cpp
#include "testsignal.h"
#include "statemachine.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    LessonStateMachine machine;
    TestSignal widget(&machine);

    machine.start();
    widget.show();

    return app.exec();
}

testsignal.h/cppの補足

シグナルとスロットの処理をしています。

testsignal.h
#ifndef TESTSIGNAL_H
#define TESTSIGNAL_H

#include <QWidget>

namespace Ui {
class TestSignal;
}
class QScxmlStateMachine;

class TestSignal : public QWidget
{
    Q_OBJECT

public:
    explicit TestSignal(QScxmlStateMachine *machine, QWidget *parent = 0);
    ~TestSignal();

private:
    Ui::TestSignal *ui;
    QScxmlStateMachine *m_machine;

public slots:
    void onStateS11();
    void onStateS12();
    void onStateS13();
    void onStateS2();
};

#endif // TESTSIGNAL_H
testsignal.cpp
#include "testsignal.h"
#include "ui_testsignal.h"

#include <QScxmlStateMachine>

TestSignal::TestSignal(QScxmlStateMachine *machine, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TestSignal),
    m_machine(machine)
{
    ui->setupUi(this);

    connect(ui->pushButtonS1, &QAbstractButton::clicked, [this] {
        m_machine->submitEvent("S1.Clicked");
    });
    connect(ui->pushButtonS2, &QAbstractButton::clicked, [this] {
        m_machine->submitEvent("S2.Clicked");
    });
    connect(ui->pushButtonExit, &QAbstractButton::clicked, [this] {
        m_machine->submitEvent("Exit.Clicked");
    });

    machine->connectToState(QStringLiteral("S11"),
                     this, SLOT(onStateS11()));
    machine->connectToState(QStringLiteral("S12"),
                     this, SLOT(onStateS12()));
    machine->connectToState(QStringLiteral("S13"),
                     this, SLOT(onStateS13()));
    machine->connectToState(QStringLiteral("S2"),
                     this, SLOT(onStateS2()));
    machine->connectToState(QStringLiteral("Final"),
                     this, SLOT(close()));

    ui->log->setText(QString());

}

TestSignal::~TestSignal()
{
    delete ui;
}

void TestSignal::onStateS11()
{
    ui->log->setText("S11");
}

void TestSignal::onStateS12()
{
    ui->log->setText("S12");
}

void TestSignal::onStateS13()
{
    ui->log->setText("S13");
}

void TestSignal::onStateS2()
{
    ui->log->setText("S2");
}

まとめ

  • 状態遷移の管理を直接、状態遷移図で使用できるのは便利です。
  • scxmlファイルを動的に読むことも可能なので、面白い使用方法もありそな感じで楽しみな機能です。

明日もQt Creator ネタです。ynumaさんの“Qt Creator Autotest Pluginについて“ です。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?