Qt (キュート)1 を触り始めました。 Qt を使ってデスクトップで動く GUI アプリケーションを作っていきます。 その過程で得たことを備忘録として残しておきます。
今回取り扱う環境は、OS X と Xcode, Qt 5.4 です。また Qt のインストール先を ~/Qt
にしています。
Qt 自体はクロスプラットフォームな開発環境になっているので、お使いの開発環境に合わせて適宜読み替えてください。
Note: こうしたツールやフレームワークの使い方について日記をつけても、 バージョンが上がり提供される API や機能が変わると、 あっという間に内容が古くなり、役に立たなくなることがしばしばあります。 とはいえ、文献はあるに越したことはありません。 Qt に限らず、ちょっとした備忘録を今後もこまめに残していこうと思います。
Qt 5.4 を手に入れる
まず手始めに、Qt を手に入れます。 Qt Community をこのページからダウンロードします。 オンラインインストーラになっているのでぽちぽちクリックしてお好きな場所にインストールします。 インストールにざっと 30 分ほどかかるので、コーヒーでも飲んでお待ちください。
qmake のパスを通す
インストールしたら、qmake
のパスを通しておきます。
僕の環境は OS X と zsh を使っているので、次のような alias を .zshrc
に追加しました。
alias qmake="~/Qt/5.4/clang_64/bin/qmake"
次のようにパスを通してもいいと思います:
export QT_SDK_ROOT=~/Qt/5.4
export PATH=$PATH:$QT_SDK_ROOT/clang_64/bin
ターミナル上で where qmake
もしくは qmake -v
と打ち、パスが通ってるか確認しておきましょう。
> qmake -v
QMake version 3.0
Using Qt version 5.4.1 in ~/Qt/5.4/clang_64/lib
qmake を使って Xcode のプロジェクトファイルを生成する
Xcode のプロジェクトファイル (.xcodeproj
) を作るには、Qt プロジェクトのディレクトリで次のコマンドを実行します。
qmake -spec macx-xcode
Qt 5.4 の Xcode でのプリプロセス
qmake
で生成された Xcode プロジェクトで、ビルドすると次のプリプロセス (Qt Preprocess) がまず走ります。
make -C /path/to/MyApp -f MyApp.xcodeproj/qt_makeqmake.mak
make -C /path/to/MyApp -f MyApp.xcodeproj/qt_preprocess.mak
これによって、Qt 特有の signal などの記述を、C++ にバインディングしてるようです。
例えば、QObject
を継承した MyClass
を定義します。
すると MyClass.h
と MyClass.cpp
から moc_MyClass.cpp
がプリプロセスによって生成されます。
音楽を再生する
Qt プロジェクトファイル(例 MyApp.pro
)に依存するフレームワークとして multimedia
を追加します。
QT += multimedia
他に qml
, quick
, widgets
に依存している場合は、このように追加します:
QT += qml quick widgets multimedia
音楽を再生する場合は、QMediaPlayer
を使います。
QMediaPlayer::setMedia
では再生する音楽の URL を QUrl
で指定することになります。
ローカルに置いてる音楽ファイルはもちろん、インターネット上の音楽ファイルも再生することができるようです。
簡単のため、QObject
を継承した MyClass
のコンストラクタに記述しました。
#include "MyClass.h"
#include <QMediaPlayer>
MyClass::MyClass(QObject *parent) : QObject(parent)
{
QUrl url = QUrl("http://a898.phobos.apple.com/us/r1000/039/Music6/v4/"
"13/22/67/1322678b-e40d-fb4d-8d9b-3268fe03b000/"
"mzaf_8818596367816221008.plus.aac.p.m4a");
QMediaPlayer* player = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
player->setMedia(url);
player->setVolume(70);
player->play();
}
ListView にスクロールバーを追加する
QML で ListView
にスクロールバーを表示する場合は、ListView
を ScrollView
の中に入れます。
ScrollView {
ListView {
// ...
}
}
ウィンドウのタイトルバーを非表示にする
ウィンドウのタイトルバーを非表示にする場合は、QML で ApplicationWindow.flags
に Qt.FramelessWindowHint
を設定します。
ApplicationWindow {
flags:Qt.FramelessWindowHint
}
QML で GUI のイベントを受け取る
TextField で onEditingFinished
イベントが発生したときにそのテキストの内容ををデバッグログに表示します。
OS X だとこのイベントは、テキストを入力後 Enter キーを押したときに発生します。
TextField {
onEditingFinished: console.log(this.text)
}
キーボードのイベントを受け取るときは Keys
を使います。
TextField {
Keys.onReleased: console.log("onReleased")
}
スコープを使って、イベントを受け取ったときの処理(シグナルハンドラー)も書けます。
TextField {
Keys.onPressed: {
if (event.key === Qt.Key_Down) {
console.log("onPressed: Key_Down");
}
}
}
console.log
の記述をみて、お気付きになった方も多いかもしれません。
QML では、JavaScript でプログラミングロジックを書くことができます。
NOTE:
event.key === Qt.Key_Down
のようにここでは==
演算子ではなく、===
演算子を使っています。 試しに、==
演算子を使って比較すると、Qt Designerで警告 (M126) が表示されます。 これは==
を使って比較するときに、2つの型が異なると強制的に型変換が行われるためです。 予期しない動作を防ぐため、代わりに===
演算子を使いましょう。 こういったところも JavaScript です。
Qt でデバッグプリント
C++ の場合は qDebug
関数を使ってデバッグプリントができます。
#include <QDebug>
void MyClass::onText(const QString& in)
{
qDebug() << in;
qDebug("ok");
}
QML の場合 console.log
が使えるようです。
Rectangle {
Keys.onPressed: {
if (event.key === Qt.Key_Down) {
console.log("key down");
}
}
Keys.onReleased: console.log("released")
}
QML から QObject (C++) の関数を呼び出す
QQmlApplicationEngine::rootContext
で QQmlContext
を取得して、
QQmlContext::setContextProperty
で QObject
を設定する形になります。
余談ですが、コンテキストにオブジェクトのポインタを設定するところは JavaScriptCore や V8, Lua などのスクリプトエンジンのバインディングと似ていますね。
例を載せておきます。
main.cpp
:
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "MyClass.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
MyClass myClass;
engine.rootContext()->setContextProperty(QStringLiteral("myClass"), &myClass);
return app.exec();
}
MyClass.h
:
#include <QObject>
class MyClass : public QObject {
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0);
~MyClass();
Q_INVOKABLE void onEditingFinished(const QString& text);
};
QML では QQmlContext::setContextProperty
に設定したオブジェクト名 (myClass
) を使って、C++ の関数を呼び出すことができます。
TextField {
onEditingFinished: myClass.onEditingFinished(this.text)
}
参考文献
- JavaScript Expressions in QML Documents | Qt QML 5.4 - QML の中で記述できる JavaScript について
- 比較演算子 - JavaScript | MDN -
==
演算子と===
演算子の違いについて
-
発音は "cute" (キュート)が一般的だそうですが、"CUE-TEE" あるいは "Q-T" (キューティー)という発音ももちろん通じるそうです。 ↩
Leave a Reply