Macようのパッケージを作成するときは。

$ macdeployqt <appname>.app/

で、必要なライブラリを拾って集めてくれるのですがQtQuick 2.0用のインポートライブラリが不足してしまいます。
これを入れればQtQuickアプリとしての最低限HelloWorldが動く内容になります。

追加するにはWindowsやLinuxのようにただコピーするだけではダメなので「otool」と「install_name_tool」を使って手を加えます。
それでは、「QtQuick.2/libqtquick2plugin.dylib」を追加する手順です。
Qt 5.0.2での例です。

$ ~/Qt5.0.2/5.0.2/clang_64/bin/macdeployqt HelloWorld.app/
$ mkdir HelloWorld.app/Contents/qml
$ cp -R ~/Qt5.0.2/5.0.2/clang_64/qml/QtQuick.2 HelloWorld.app/Contents/qml
$ otool -L HelloWorld.app/Contents/qml/QtQuick.2/libqtquick2plugin.dylib | grep Qt
HelloWorld.app/Contents/qml/QtQuick.2/libqtquick2plugin.dylib:
/Users/iori/Qt5.0.2/5.0.2/clang_64/lib/QtQuick.framework/Versions/5/QtQuick (compatibility version 5.0.0, current version 5.0.2)
/Users/iori/Qt5.0.2/5.0.2/clang_64/lib/QtQml.framework/Versions/5/QtQml (compatibility version 5.0.0, current version 5.0.2)
/Users/iori/Qt5.0.2/5.0.2/clang_64/lib/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.0.0, current version 5.0.2)
/Users/iori/Qt5.0.2/5.0.2/clang_64/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.0.0, current version 5.0.2)
/Users/iori/Qt5.0.2/5.0.2/clang_64/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.0.0, current version 5.0.2)


ここまでで、QtQuickとQtQmlとQtNetworkとQtCoreとQtGuiを参照していることがわかります。
ただし、絶対パスで指定されているので、intall_name_toolを5回実行して1つずつ参照先を実行ファイルからの相対パスへ書き換えます。
で、面倒なので以下のスクリプトを使うと少し楽になります。

#!/bin/bash

QTPATH=/Users/iori/Qt5.0.2/5.0.2/clang_64/
LIBPATH=$1
CMD="install_name_tool -change"
ABSPATH1=lib/
ABSPATH2=.framework/Versions/5/
RELPATH1=@executable_path/../Frameworks/
RELPATH2=.framework/Versions/5/

count=1
for arg in $@
do
if [ $count -gt 1 ] ; then
$CMD ${QTPATH}${ABSPATH1}${arg}${ABSPATH2}${arg} ${RELPATH1}${arg}${RELPATH2}${arg} $LIBPATH 
fi
count=$(($count+1))
done

$ macdeployhelper.sh HelloWorld.app/Contents/qml/QtQuick.2/libqtquick2plugin.dylib QtQuick QtQml QtNetwork QtCore QtGui

で、下のように書き換わります。

$ otool -L HelloWorld.app/Contents/qml/QtQuick.2/libqtquick2plugin.dylib | grep Qt
HelloWorld.app/Contents/qml/QtQuick.2/libqtquick2plugin.dylib:
@executable_path/../Frameworks/QtQuick.framework/Versions/5/QtQuick (compatibility version 5.0.0, current version 5.0.2)
@executable_path/../Frameworks/QtQml.framework/Versions/5/QtQml (compatibility version 5.0.0, current version 5.0.2)
@executable_path/../Frameworks/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.0.0, current version 5.0.2)
@executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore (compatibility version 5.0.0, current version 5.0.2)
@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui (compatibility version 5.0.0, current version 5.0.2)


あとは、がんばって必要なプラグインとかを調べる感じです。


Ubuntu for PhoneでQt Quickアプリを動かしてみた

今ちょっと話題のUbuntu for Phoneのイメージが公開されたので以前作ったアプリを移植してみました。

まずターゲットにしたのはRewitQだったのですがXmlListModelのonItemsInsertedが使えなくて詰んだので簡単そうなゲームにしてみました。
なので、これ「SpaceQB

Qt Quick 1.1で作成していたので2.0への移植。
いちおう遊べます。

ソースはアーカイブしておきましたので参考にどうぞ。
ソースアーカイブ

Ubuntu用のプロジェクトテンプレートにもとのソース(GoogleCode)をコピーしてルートのエレメントの中身をMainViewにコピーしてダブってるwidthとかを消して、上の方にあるisMobileプロパティをtrueにすればボタンが表示されます。
あと、パーティクルのあたりもコメントアウトしてます。(使い方が変わってたので。。。)
デバイスへ転送前にCtrl+Rとかでデスクトップで実行できるのを確認すると良いです。

開発環境の整え方はこちら
[Ubuntu] Touch Developer Preview and SDK Alpha を試してみました」(adakodaさん)

以下、スクショ
spaceqb_screenshot1.png
spaceqb_screenshot2.png

QML(Qt)のグラデーションを任意の方向にする

QMLのグラデーションは通常Gradientエレメントを使用しますが、縦方向にしか設定できません。
そんな話題があったので試しに作ってみました。

通常はこんな感じ。
Rectangle {
    width: 100; height: 100
    gradient: Gradient {
        GradientStop { position: 0.0; color: "red" }
        GradientStop { position: 0.33; color: "yellow" }
        GradientStop { position: 1.0; color: "green" }
    }
}

/// ポイント ///
・グラデをかけたい四角をクリップ設定にして、中にグラデをかけた四角を置く
・rotationで中の四角を回転させる(使い勝手がいい)
・親のサイズに合わせて調度良くリサイズをする
・関数でもバインドが働く
・もっと効率いい計算方法あったら教えて下さい

サンプルコード(拡張エレメント込)はこんなかんじです。
エレメント名がMSっぽいとかは気にしたらダメです。
サンプルはウインドウサイズを変更するとグラデの角度が変わります。

実際に使用するときは、親のエレメントのclipをtrueにします。

サンプルのスクリーンショット
qt-gradient-free-angle.png
呼び出し元
import QtQuick 2.0

Rectangle {
    width: 600
    height: 400
    color: "black"

    Rectangle{
        anchors.centerIn: parent
        width: parent.width / 3
        height: parent.height / 3
//        clip: true

        GradientEx{
            id: grad
            gradient: Gradient{
                GradientStop { position: 0.0; color: "red" }
                GradientStop { position: 0.33; color: "yellow" }
                GradientStop { position: 1.0; color: "green" }
            }
            rotation: (2 * (parent.x - 400)) % 360
        }

        //ちゃんとグラデの四角が良いサイズになってるか確認する用の四角(親のclipは解除して確認する)
        Rectangle{
            anchors.fill: parent
            opacity: 0.5
        }
    }

    Text{
        text: "angle=" + grad.rotation
        color: "white"
    }
}

拡張したグラデ
import QtQuick 2.0

Rectangle{
    anchors.centerIn: parent
    width: calcWidth()
    height: calcHeight()

    //ラジアンを予め計算しておく
    property real rad: calcRad()
    //角度は0~90にしないと面倒なので
    function calcRad(){
        var r = rotation;
        while(r > 90){
            r -= 90;
        }
        while(r < 0){
            r += 90;
        }
        return r * Math.PI / 180;
    }
    //0~90度を基準に90度ごとにwidthとheightにかけるcosとsinが入れ替わる
    //なのでマイナス側の-90~0は、入れ替わりになるように90度ずらして判定する
    function calcWidth(){
        var len = 0;
        var r = rotation >= 0 ? rotation : -(rotation - 90)
        if((0 <= r && r <= 90) || (180 < r && r <= 270)){
            len = parent.width * Math.cos(rad) + parent.height * Math.sin(rad);
        }else if((90 < r && r <= 180) || (270 < r && r <= 360)){
            len = parent.width * Math.sin(rad) + parent.height * Math.cos(rad);
        }else{
            len = parent.width * Math.cos(rad) + parent.height * Math.sin(rad);
        }
        return len;
    }
    function calcHeight(){
        var len = 0;
        var r = rotation >= 0 ? rotation : -(rotation - 90)
        if((0 <= r && r <= 90) || (180 < r && r <= 270)){
            len = parent.width * Math.sin(rad) + parent.height * Math.cos(rad);
        }else if((90 < r && r <= 180) || (270 < r && r <= 360)){
            len = parent.width * Math.cos(rad) + parent.height * Math.sin(rad);
        }else{
            len = parent.width * Math.sin(rad) + parent.height * Math.cos(rad);
        }
        return len;
    }
}

QtとWindowsと日本語と

Windows環境での注意点です。

WindowsでVisual Studioを使用してビルドするとき、並列ビルドをするためにjom.exeを使用しています。
ですが、このツール日本語(というかASCIIコードじゃない文字というべき?)を含んだパスにあるファイルをコンパイルできません。
なので、以下のパスに日本語が含まれないか注意してください。

・Qtのインストールパス
 日本語を使用しないでください。
・キット名
 ビルドパスのデフォルトに設定されて毎回変更しないとで面倒です。
・プロジェクトのパス
 日本語を使用しないでください。
・ユーザーフォルダ名
 ユーザーフォルダ内のテンポラリを使用するので回避できません。
 Windowsのログイン名を日本語にしてる場合などはユーザー作りなおすのが無難です。

もしどうしても日本語を使用したいときは、オプションの「ビルドと実行」の「概要」タブにある「nmakeの代わりにjomを使用する」のチェックを外してください。


こんなこと意識してた人いるかワカリマセンが。

Qt4からQt5になって気になった動作の変化についてです。
どっちが本来の仕様かはわからないのですが。知ってる方いたら教えて下さい。
Qt5の方が本来の動きな気がしますが。。。

Qt4のときは、opacityが0厳密には0.001未満のとき設定したエレメントとその中にあるエレメントは無いことになってMouseAreaエレメントなどが配置してあっても「無視」されました。
Qt5では、単純に見えないだけで無視されなくなりました。Qt5でQt4の頃のような動作にしたいときは、enabled: falseとする必要があります。

それだけなんですけどね。

なので以下のサンプルをQt4(qmlviewer)とQt5(qmlscene)で実行すると差がわかると思います。
Qt4で実行すると「click rect 1」とコンソールに出力されます。
Qt5で実行すると「click rect 2」とコンソールに出力されます。
import QtQuick 2.0
//import QtQuick 1.0

Rectangle {
    id: root
    width: 360
    height: 360
    Rectangle{
        anchors.fill: parent
        color: "red"
        MouseArea{
            anchors.fill: parent
            onClicked: {
                console.debug("click rect 1");
            }
        }
    }
    Rectangle{
        anchors.fill: parent
        color: "blue"
        opacity: 0
        MouseArea{
            anchors.fill: parent
            onClicked: {
                console.debug("click rect 2");
            }
        }
    }
}

Qt4.8.xをWindows(Desktop)向けにビルドする

Qt4.8.xをビルドします。
まだまだしばらくは現役っぽいですしね。

試したコミットは「8990186b15923096054d42de03cbbab9453730f3」でビルドしたらバージョン番号は4.8.5でした。


/// 環境(参考) ///
・Windows 7 Pro (64bit)
・Virtual Boxにインストール
・割り当てコア数2
・割り当てメモリ2G

注意
作業をするフォルダは「c:\qt4」として以下の説明をします。

/// 環境作成 ///
1.必要なツールをインストール
・Visual Studio 2008 (or 2005)
git


/// ビルド準備 ///
1.ソースの取得
>cd c:\
>git clone git://gitorious.org/qt/qt.git qt4
>cd qt4

2.環境変数の設定
>"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" amd64

1行目のamd64は環境にあわせて変更してください。


パスの内容はVCのバージョンによっても変わりますので調節してください。

3.ビルド
>configure -platform win32-msvc2008 -opensource -nomake examples -nomake tests -confirm-license -prefix c:\Qt\qt4.8.x\
>nmake

3.インストール
>nmake install

configreするときにprefixで指定したパスにコピーされます。


/// 注意 ///
自分がテストした状態ではWebkitの中で以下のようなエラーがでます。
DefaultLocalizationStrategy.cpp
platform\DefaultLocalizationStrategy.cpp(327) : error C2001: 定数が 2 行目に続いています。
platform\DefaultLocalizationStrategy.cpp(327) : fatal error C1057: マクロ展開中に予期せぬ EOF を検出しました。

C:\qt4\src\3rdparty\webkit\Source\WebCore\platform
line:327
return WEB_UI_STRING("Look Up """, "Look Up context menu item with selected word").replace("", truncatedStringForLookupMenuItem(selectedString));

こんな感じの行があって明らかに「"」が悪さしてそうだったのでシングルクオートに置き換えたらビルドできました。

QMLでidを参照するときのイメージ

QMLのid参照は少し不思議な感じを受けるのでざっと図にしてみました。
それを実際に書いて動かした図も載せました。
x, yにを設定しているのでなかなかややこしくなっててすみません。

/// ポイント ///
・同一QMLファイル内のidは親子関係に関係なく参照可能
・親のQMLファイル内のidは自由に参照可能かつ何代でもOK
 図:Foo.qmlとHee.qmlからHoge.qmlのlv2にアクセスしてるところ
・自分に配置したQMLファイル内のidへの参照は不可
 つまり親を中継して隣に配置されたQMLファイル内のidへはアクセス出来ない
 QMLファイルを配置すると「new Foo(Hoge::root)」とされるイメージなので親方向へのアクセスは自由だけど隣は不可
 childerenやresourcesプロパティを使用すれば親を中継して隣のエレメントのオブジェクトにアクセスすることは可能だと思いますけどね。

続きにサンプルソースがあるので見比べないと図が理解し難いかもです。。。


/// イメージ図 ///

イメージ図を実際に動かしたところ



Qt Quick入門の記事を書きました

技術評論社さんの月刊誌Software Design 2003年1月号に記事を書きました。
初の商業誌への寄稿でドキドキです。

Qt Quickを知らない方に体験していただけるような内容でがんばって書きました。
ぜひ、手にとって試していただけると嬉しいです。

セットアップのところとかがQtSDKがなくなった関係で若干面倒になってしまったのと、Qt5のRC版がリリースされてダウンロードしてくるところが若干紛らわしくなってしまったところが悔やまれるところでしょうか。
今回の記事はあえて4系で説明をしているので。

これからもいろいろな場面で情報配信していきますよ!
よろしくお願いします。

ご購入頂いた方へ追記
 環境構築でQt Libraries 4.8.3をダウンロードするように記載していますが、執筆時点とずれてしまい現状は4.8.4です。
 紛らわしくなってしまいましたがご注意ください。

QML(Qt)でスクリーンの情報を取得する

Qt5で追加されたエレメントの紹介です。
QMLからシステム側へアクセスできるエレメントが増えましたね。

紹介する「Screen」エレメントは、解像度と回転状態を取得できます。
(が、試した段階では下記のように微妙な動きでした)

/// 確認環境 ///
・Windows 8 Pro
・モニター2枚

/// 取得できる情報 ///
・width : モニターの横幅
・height : モニターの高さ
・orientation : 現在の向き
・primaryOrientation : 基本の向き?

横幅と高さはプライマリモニターのみの情報が取得できました。
orientationはランドスケープ固定でした。
primaryOrientationは画面の回転にあわせて変化しました。

/// 向き情報 ///
向き情報はenumでQt::ScreenOrientationが取得できて内容は以下の感じ。
Qt::PrimaryOrientation 0x00000000
Qt::LandscapeOrientation 0x00000002
Qt::PortraitOrientation 0x00000001
Qt::InvertedLandscapeOrientation 0x00000008
Qt::InvertedPortraitOrientation 0x00000004


/// 注意 ///
・QtQuick.Windowモジュールをインポートする
・実行するときは以下のファイルが必要
 \import\QtQuick\Window.2\plugins.qmltypes
 \import\QtQuick\Window.2\qmldir
 \import\QtQuick\Window.2\windowplugin.dll
・情報はリードオンリー(当たり前


そろそろQt5がリリースされそうな頃合いで楽しみですね。
さて、Qt Quick2で作られたアプリを配布するときのパッケージ作成についてまとめました。
やること自体は以前の「QML(Qt)アプリケーションの配布方法(Windows編)」と同じですがDLLの構成が変わっています。


/// 今回のポイント ///
・必要なDLLを同梱する必要がある
・DLLの入手元はコンパイラを「MinGW」と「VisualC++」のどちらを使うかで変わる
・Qt Quickアプリケーションの場合は、qmlファイルも同梱する
Qtプラグインを使用していないつもりで必須なプラグインがある
QMLでインポートするモジュールはすべてDLLが必要


/// DLLの入手パス ///
Qt DLL : <Qt5Dir>\bin
Import Module : <Qt5Dir>\imports
Plugin : <Qt5Dir>\plugins

VisualStudio2008 : C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist
(x86用とかamd64用とかが保存されてますので適宜。。。)


/// DLLとQMLの配置場所 ///
基本的に実行ファイル(*.exe)と同じフォルダに配置します。
QMLファイルはビルドフォルダにできる「qml」フォルダを丸ごと実行ファイルと同じフォルダにコピーします。
 実行ファイル : <App>\*.exe
 必須DLL : <App>\*.dll
 Qtプラグイン : <App>\<qtplugins>\*.dll
 QMLモジュール : <App>\<qmlmodule>\*.dll
 QMLファイル : <App>\qml\<project name>\*.qml , *.js


/// コンパイラに依存して必要なDLL ///
・MinGW
 mingwm10.dll
 libgcc_s_dw2-1.dll
・VC++
 msvcr90.dll
 msvcp90.dll


/// QtQuick2として必要なDLL ///
・メイン
 QtCore5.dll
 QtGui5.dll
 QtNetwork5.dll
 QtQml5.dll
 QtQuick5.dll
 QtV85.dll
・インポートモジュール
 QtQuick.2\qmldir
 QtQuick.2\qtquick2plugin.dll
・プラグイン
 platforms\qminimal.dll
 platforms\windows.dll


/// 必要なDLLの確認方法 ///
Dependency Walker」というアプリを使用して確認します。
Dependency Walkerを実行して確認したい自分のアプリの実行ファイル(*.exe)を開きます。
不足しているDLLがあると印がつきますので不足しているDLLを実行ファイルと同じディレクトリに置いて開き直します。


/// Qtプラグインを使用している場合に必要なDLL ///
DBアクセスや画像処理、文字コード関連の処理などなど。
たくさんあるので幾つか例をピックアップします。
・画像関連
 imageformats\qgif4.dll
 imageformats\qico4.dll
 imageformats\qjpeg4.dll
 imageformats\qmng4.dll
 imageformats\qsvg4.dll
 imageformats\qtiff4.dll
・DBアクセス
 sqldrivers\qsqlite4.dll