はじめに
QML は JavaScript ベースなので、ファイルを扱うことができません(XHR とかは出来ます)。なので、特定のディレクトリに含まれる画像をスライドショーしたいなぁ、と思っても、画像パスのリストを JS から取得することが出来ず、ファイル名を JS に配列で列挙する、という形になってしまいます。そこでこれを解消するためには、C++ でそのリストを作成して上げて結果を QML 側に渡してあげる、という処理が必要となります。入用になって調べてみたのでメモします。
QML
import QtQuick 1.1 Rectangle { id: window width: 360 height: 360 property string picDirPath : "/Path/to/your/picture/directory" property variant picPaths : [] property int picIndex : 0 Image { id: picture width: parent.width height: picture.width * 0.75 } Timer { id: timer running: true interval: 30 repeat: true onTriggered: { if (window.picIndex >= window.picPaths.length) { window.picIndex = 0; } picture.source = window.picPaths[window.picIndex++]; } } function onReadDir(fileNames) { var list = []; fileNames.forEach(function(fileName) { if (fileName.match(/jpg$/i) !== null) { list.push(fileName); } }); window.picPaths = list; } }
この picDirPath プロパティを C++ で取得して、そのディレクトリ内の画像を読み込み、onReadDir の引数に結果を流し込む、という流れになります。
C++
#include <QApplication> #include <QGraphicsObject> #include <boost/filesystem.hpp> #include <boost/foreach.hpp> #include "qmlapplicationviewer.h" namespace fs = boost::filesystem; Q_DECL_EXPORT int main(int argc, char *argv[]) { QScopedPointer<QApplication> app(new QApplication(argc, argv)); // QML から GUI を作成 --> フルスクリーンで表示 QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/SlideShow/main.qml")); viewer.showFullScreen(); // ルート要素を取得 QGraphicsObject* root_obj = viewer.rootObject(); // 画像を格納したフォルダのパスを QML から読み出す QString pic_dir_path = root_obj->property("picDirPath").toString(); // 特定のフォルダ内のファイル名を洗い出す QVariantList list; const fs::path path(pic_dir_path.toStdString()); BOOST_FOREACH(const fs::path& p, std::make_pair(fs::directory_iterator(path), fs::directory_iterator())) { if (!fs::is_directory(p)) { list << p.c_str(); } } // QML 内で定義した関数を呼び出す QMetaObject::invokeMethod(root_obj, "onReadDir", Q_ARG(QVariant, list)); return app->exec(); }
QML 内のプロパティは以下のようにして取得出来ます。
viewer.rootObject()->property("hogehoge")
あとは toHoge() をしてあげれば、所望の型で変数が取得出来ます。
逆に QML 側の関数を呼ぶ際は以下のようにします。
QMetaObject::invokeMethod(ルートオブジェクト, "QML 側の関数名", Q_ARG(型名, 引数に与える変数), ...);
とても簡単で素晴らしい。。
.pro
Boost.Filesystem を使ったので以下の記述を追加。
LIBS += -lboost_filesystem -lboost_system