QML(Qt)でJavaScript(処理)を分離する

QMLでは処理をJavaScriptで書くことができます。
共通で使うような内容は関数化したりして別のファイルにまとめることができます。

細かい解説はこちら : Integrating JavaScript
今回紹介していませんが、QMLのシグナルをJsで受け取る方法も書いてあります。


/// 今回のポイント ///
・QMLファイルからインポートして簡単に使用可能
・JavaScriptファイルからJavaScriptファイルをインポートできる
・ステートレスライブラリにするかどうかでインスタンスの出来方が変わる



/// 作成方法 ///
・プロジェクトを右クリックして「新しいファイルを追加」を選択
 

・「QML」→「JSファイル」を選択
 

・ファイル名を指定
 フォルダにまとめる場合は「参照」からフォルダを作成してから指定する
 

・ステートレスライブラリにするかを決める
 詳細は後述
 

・プロジェクトに追加するかとかバージョン管理の設定
 とりあえずそのままで
 



/// インポートの方法 ///
・QMLファイルからインポートして簡単に使用可能
・JavaScriptファイルからJavaScriptファイルをインポートできる

QMLでは、「import "hoge.js" as Hoge」といった記述をします。
そうすると「Hoge.func();」といった感じで関数を実行できます。
「Hoge」というインスタンスが作成されるイメージです。

JavaScriptファイルでは、「Qt.include("hoge.js")」といった記述をします。
そうするとインポートしたファイルで定義した関数がそのまま使用できます。

(サンプルは後でまとめてです。)


/// ステートレスライブラリにするかどうかでインスタンスの出来方が変わる ///
これ重要です。
実は下のサンプルのJSファイルは「ステートレスライブラリ」として作成しています。
ウィザードでチェックをチェックすると1行目の「.pragma library」が追加されます。
コード上の違いは以上です。

サンプルは2ヶ所の文字列をクリックした時にデバッグコンソールにクリックした回数を表示するようになっています。
サンプルそのままの場合は、どちらを押しても回数が通しの番号で出力されます。
逆に、「.pragma library」をコメントして実行するとそれぞれ独立して回数がカウントされます。
つまり
 ・ステートレスライブラリ : アプリ全体でインスタンスが共有される
 ・not ステートレスライブラリ : 読み込んだQML毎でインスタンスが別々になる
と、なります。
(そもそもインスタンスという表現があっているかわかりませんが・・・。)

どちらを使うかは状況に応じて変わるので目的を考えて設定してください。


サンプルは一気にほぼ最終形態で行きます。

本体のQMLファイル
import QtQuick 1.0
import "js/Util.js" as Util // JSファイルをインポート

Rectangle {
    width: 360
    height: 360
    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }

    Text {
        anchors.centerIn: parent
        text: "Output debug string."
        MouseArea{
            anchors.fill: parent
            onClicked: {
                Util.debugOutput("click! " + Util.getCount());
            }
        }
    }

    Message {
        text: "Output debug string2"
    }
}

分離したパーツのQMLファイル
// Message.qml
import QtQuick 1.0
import "js/Util.js" as Util


Text {
    x: 0; y: 0;
    MouseArea{
        anchors.fill: parent
        onClicked: {
            Util.debugOutput("click!(in module) " + Util.getCount());
        }
    }
}

QMLからインポートされるJavaScriptファイル
// Util.js
.pragma library   // ステートレスライブラリにすると追加される
Qt.include("Debug.js")

// デバッグ文字列をコンソールへ出力
function debugOutput(message) {
    debugOutputToConsole(message);
}


var counter = 0;

// カウンタ値を取得してインクリメント
function getCount(){
    return counter++;
}

JavaScriptファイルからインポートされるJavaScriptファイル
// Debug.js
.pragma library   // ステートレスライブラリにすると追加される

var is_debug = true;

// デバッグ文字列をコンソールへ出力
function debugOutputToConsole(message) {
    if(is_debug){
        console.debug(message);
    }
}