QML(Qt)でカスタムQMLエレメントを作る

QMLではオリジナルのエレメントを作成する事ができます。
標準で用意されている機能では不足する部分などを簡単に補えます。

今回は細かいプロパティとかの方法はパスです。
オリジナルのエレメントをどのように扱って行くかの話です。

公式の以下のページで解説されてますしサンプルもあるのでお試しも非常に簡単。
Tutorial: Writing QML Extensions with C++


/// 作成方針 ///
・エレメント自体をアプリ本体(exe)に組み込む
・プラグインとしてライブラリにする

の、2つの方法があります。
どのように提供するかで方針がわかれると思います。
エレメントだけをバイナリで配りたいのであれば後者なのですが少々使い勝手が悪い(後述)です。
個人利用だったりソースをgit hubやgoogle codeで自由にDLできるようにしてしまうのであれば、前者のほうが扱い的に楽だと思います。

と、ちょっと趣違いますが大事な方針
・プロジェクトは独立させる


/// 作成方法 ///
  プロジェクト作成
 Qt Creatorで用意されているウィザートではプラグインを作成することになりますが、これを使います。
 あとでどっちの方針にも持っていけるのでよろしいかと。
  

  プロジェクト名
  

  対象プラットフォーム
  いつでも追加できるのでお好みで。
  

  実際に使用するエレメント名
  uriはunix系OSへプラグインをインストールする際に使用します。
  

  バージョン管理系の設定
  お好みで。
  

  スケルトン完成
  


/// エレメントの使用方法 その1(プラグインとして) ///
1.リリースでビルド
2.適当なQt Quickアプリケーションを作成する
3.プラグインのコピー
 CustomElement.dllとqmldir(プロジェクトにあるやつ)を「2」で作ったプロジェクトの「main.qml」と同じディレクトリにコピーする。
4.Hello Worldな状態に「CutomElement{}」を追加する
 CutomElementの下に赤の波線が表示されて「不明な型」として警告が表示されますがOKです。
import QtQuick 1.1

Rectangle {
    width: 360
    height: 360
    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    //カスタムエレメント!!
    CustomElement{
    }
}
5.実行する
 「Hello world」が表示されればOKです。
 今回はスケルトン状態で表示するものが無いのでエラー無しで実行できればOK。
 下のようなエラーがでたらなにか間違えてます。
 すでに他のプラグインがあってそっちの情報もqmldirに書いてあるのにdllが無いとかあってもエラーになります。
file:///D:/QtProjects/sample/qml/PluginLoadText/main.qml:17:5: CustomElement is not a type 
         CustomElement{ 
         ^ 
 以上、簡単ですね。

 プラグインのDllを配置することが「CustomElement.qml」を作成するのと同じイメージです。
 Dllを配置するパスが気に入らない場合は、qmldirの中身を調整してください。
 qmldirの記述方法の詳細はコチラ「QML Modules - Writing a qmltypes file
 今回は、「plugin 」です。



/// エレメントの使用方法 その2(アプリに組み込む) ///
1.priファイルの作成
 他のプロジェクトからソースにアクセスできるようにします。
 proファイルに記述されてる以下の情報を新規で作ったpriファイルへ移動させます。
  SOURCES
  HEADERS
  QT
 その他にも必要があればpriファイルへ追加していきます。
 ただし、hogehoge_plugin.cppと.hは移動させません。いらないので。
 priファイル
QT += declarative

INCLUDEPATH += $$PWD

# Input
SOURCES += \
    $$PWD/customelement.cpp

HEADERS += \
    $$PWD/customelement.h

OTHER_FILES = qmldir
 proファイル
include(customelement.pri) #これ追加して読み込みます

TEMPLATE = lib
TARGET = CustomElement
CONFIG += qt plugin

TARGET = $$qtLibraryTarget($$TARGET)
uri = jp.xii.relog.customelement

SOURCES += \
    customelement_plugin.cpp #残します

HEADERS += \
    customelement_plugin.h #残します

#... 以下略
 priファイルで、INCLUDEPATHの追加と、ファイル名の前に「$$PWD/」を追加するのがポイントです。
 こんな感じになります。
 

2.プロジェクトにに追加する
 使用する側のプロジェクトのproファイルでincludeします。
include(../CustomElement/customelement.pri)

# Add more folders to ship with the application, here
folder_01.source = qml/PluginLoadTest
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01

#... 以下略
 プロジェクトのツリーがこんな感じになってソースが使えるようになります。
 

3.QMLにインポートできるようにする
 main.cppでQMLでエレメントをインポートして使えるようにするためのコードを追加します。
#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <customelement.h> // 追加

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));

    // 追加
    qmlRegisterType<CustomElement>("CustomElements", 1, 0, "CustomElement");

    QmlApplicationViewer viewer;
    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/PluginLoadTest/main.qml"));
    viewer.showExpanded();

    return app->exec();
}
qmlRegisterTypeの一つ目の引数がインポートする時の名称です。
同じにしても構いません。

4.QMLに組み込む
 インポートして使用します。
 プラグイン形式の時との決定的な違いは、「不明な型」の警告がでなくてコード補完が使えることです。
import QtQuick 1.1
import CustomElements 1.0   // インポートする

Rectangle {
    width: 360
    height: 360
    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    //カスタムエレメント!!
    CustomElement{
    }
}

5.実行する
 「Hello world」が表示されればOKです。

最初だけちょっと準備的な作業がありますがコチラのほうが使い勝手が良いと思います。