進化するQt-Qt最新事情2009

第3回Qt 4.5最新動向

はじめに

Qt 4.5とQt Creator 1.0は2009年3月初めにリリースされました。それから時間も経ち、8月末までに2回バグ修正バージョンがリリースされています。

表1 Qt 4.5.xリリースの軌跡
リリース日バージョン
2009/3/3Qt 4.5.0、Qt Creator 1.0
2009/4/23Qt 4.5.1、Qt Creator 1.1
2009/6/25Qt 4.5.2、Qt Creator 1.2

リリースされてすでに半年以上が過ぎていますので、Qt 4.5の新機能については、ここでは概要を紹介するに留めます。次に、表立って取り上げられてはいませんが、Qtの中心的な機能であるオブジェクトシステムにも変更が加えられているので、その内容を説明します。そして、次回以降で、Qt 4.5で大きく変わったQtに付属するGUIツールQt DesignerとQt Linguistについて詳しく新機能を説明します。

Qt 4.5の改善と新機能の概要

Qt 4.5: What's New in Qt 4.5にある、Qt 4.5の改善や新機能のまとめを元に説明します。

Qt WebKitインテグレーション

Qt WebKitインテグレーションはQt 4.4から追加された機能で、WebKitをブラウザとしてQtから利用できるだけでなく、QtのウィジェットをWebコンテンツと混在させて、アプリケーションを開発できる機能です。Qtに同梱されているWebKitが更新され、以下の機能が追加されて、ほぼフルブラウザと呼べるようになりました。

  • ACID3スコアが100/100になり、Web標準をクリアしたWebブラウザがQtで利用できるようになりました。
  • イメージとフォントのフルページズーミング
     イメージとフォントの両方、あるいはどちらか片方のズーミングができます。

  • CSSベースの図形変換とアニメーション

  • JavaScriptエンジンの速度改善

  • NetscapeプラグインAPI(NPAPI)
     UNIX/Linux X11、Mac OS X、Windowsで使用できます。残念なことですが、これら以外のプラットフォームへの対応予定はロードマップにありません。Flash Playerプラグインなどが使え、YouTubeのFLV動画再生ができます。SWFも、Linuxでは32ビットと64ビットで共に使えます。しかし、Mac OS Xでは、SWFはマウス操作もキー操作もできないため、SWFは扱えませんでした。同じようにWebKitを使っているSafariでは問題なくSWFを使えます。

  • Phononインテグレーション
     HTML 5のオーディオとビデオの各エレメントによる音声と動画がサポートされています。

  • クライアントサイドデータベースストレージ
     QtとのインターフェースのためにQWebDatabaseが追加され、 QWebSettingsにsetOfflineStoragePath()、 offlineStoragePath()、 setOfflineStorageDefaultQuota()、 offlineStorageDefaultQuota()などのメソッドが追加されています。

パフォーマンス改善

  • X11でのMIT-SHM(MIT Shared Memory Extension)の利用
     昨年の特集記事で触れたように、MIT-SHMを利用することで、イメージデータがメモり共有され、X11 のクライアントとサーバ間での一番のボトルネックが解消され、イメージの回転や拡大縮小表示で、劇的な描画速度改善がされています。次項のラスターグラフィックスエンジンを指定すると、MIT-SHMが有効になります。

  • ラスターグラフィックスシステム
     描画エンジンがプラグイン化され、ラスター、OpenGL、プラットフォーム固有のものから、目的に合ったものを選択できるようになりました。コマンドラインオプション-graphicssystemでraster、opengl、nativeを指定するか、QApplication::setGraphicsSystem ⁠const QString& system)で、グラフィックシステムを切り替えられます。

  • QTestLibへのベンチマーク機能の追加
     実時間、CPUクロックカウント、Valgrind/Callgrind、イベントカウントなどの計測機能があります。

  • OpenGL ES 2.0ベースの描画エンジン
     OpenGL描画エンジンとしてOpenGL ESも使えるようになりました。

Mac OS X Cocoa サポート

Qt/Mac OS XはCarbonで実装されています。Cocoaのサポートは、64ビット対応が一番の目的です。64ビットはCarbonではサポートされず、Cocoaのみでのサポートとなったため、Qtが64ビット対応するには、Cocoaでの再実装が必要でした。

configureのデフォルトはCarbonで、Cocoaや64ビットにするには表2のようにオプション指定します。

表2 Qt/Mac OS Xのconfigureオプション
オプション結果
-cocoa32ビット Cocoa
-arch x86_6464ビット Cocoa
-arch "x86 x86_64"32ビットと64ビット Cocoa

今後のリリースではCocoaがデフォルトになり、Carbonサポートが打ち切られる予定です。

QMacCocoaViewContainerとQMacNativeWidgetの2つのクラスが追加され、Cocoaの独自機能と部品もQtで扱えます。

また、リリース直後のせいか、QTransformationで射影変換をすると、Carbonでは問題がないのですが、QPainter::drawLine() で描いた線分の変換結果が間違っています。ラスターエンジンにすると変換結果は正しくなりますが、間違った線分が一瞬描かれた後に正しい線分が描かれます。

Cocoaサポートとは関係がありませんが、GCC 4.2も使えるようになっています。

Windows CEサポート

Windows CEでPhononとWebKitが利用可能になりました。

QtXmlPatternsでXSLTサポート

XQueryとXPathをサポートしているQtXmlPatternsで、XSLTが利用可能になりました。

Qtスクリプトデバッガ

QtのECMAScript(JavaScript)をベースにしたQtScriptモジュール用のGUIデバッガが追加されました。

OpenDocumentファイルフォーマットの出力

PostScriptやPDFに加えて、ODFの出力もできるようになりました。Qt DemosのText Editで試してみると、日本語の扱いもできています。PDF出力が追加されたときには、文字表示でジャギーが目立って、改善を待たなければなりませんでしたが、ODF追加ではそのようなことはありませんでした。

この機能の説明とサンプルコードは、Writing ODF Files with Qtのページから入手できます。

ネットワークプロキシーサポートの改善

Qt DesignerとQt Linguistの改良

これについては別項で詳しく説明します。

グラフィック機能の改善

  • トップレベルウィンドウの透過度設定Qt 4.5: QWidget Class Reference
     ウィンドウ属性Qt::WA_TranslucentBackgroundが追加され、トップレベルウィンドウに、ピクセル単位で透過度を設定できるようになりました。X11とWindowsでは、ウィンドウフラグQt::FramelessWindowHintの設定が必要で、以下の使用条件があります。

    • X11…ARGBビジュアルとコンポジットウィンドウマネージャがサポートされたXサーバが必要

    • Windows…Windows 2000以降

マウスイベントが効くかどうかが透明度で決まり、その透明度がプラットフォームによって違っているので、扱いに注意が必要です。

スタイルシート

Mac OS Xでもスタイルシートがウィジェットで使えるようになりました。

バグ修正や追加機能の調べ方

以前のQtは、リリース情報は概要程度で、変更履歴を読んでも、どのようなバグが修正されたのかは、ほとんどわかりませんでした。最近は、以前に比べれば詳しく書かれるようになり、Task TrackerGitリポジトリのログを併用すれば手がかりが掴め、Gitリポジトリから修正パッチも作ることもできるようになっています。しかし、バグ修正や追加機能を調べるには、以下のような地道な手間が必要です。

  • リファレンスのWhat's New in 4.5を読む

  • 変更履歴changes-4.5.0を読む

  • Qt Assistantの全文検索機能でintroducedをキーにして検索し、さらにテキスト検索機能でintroduced in 4.5と付記されている記述を調べる。

    • (1)Qt Assistantのサイドバーの検索でintroducedをキーにして検索
    • (2)検索された項目をひとつずつ開きながら
    • (3)編集の検索機能で Qt 4.5 を検索して、記述内容を調べる
  • ソースコードを見て初めてわかる機能 br>

    リファレンスにも変更履歴にも書かれていなくても、ソースコードを見ていて気が付き、開発元に確認するとサポートされている機能だと返事があったりします。

オブジェクトシステムの変更

QMetaObject

QMetaobjectのextradata の構造が変わり、static_metacall が追加されています。これにより、新しいメソッド newInstance() が呼び出されるとインスタンスが生成できます。つまり、コンストラクタのイントロスペクションができ、コンストラクタの呼び出しが可能 ⁠Invokable⁠⁠ になっています。これに関連して、以下のメソッドが追加されています。

QMetaMethod QMetaObject::constructor()
int QMetaObject::constructorCount()
int QMetaObject::indexOfConstructor()
QObject* QMetaObject::newInstance()

コンストラクタを呼び出し可能にするには、Q_INVOKABLE がコンストラクタの宣言に指定してある必要があります。Qt 4.5 でこの指定がされているコンストラクタは、以下のもののみです。

Q_INVOKABLE explicit QObject(QObject *parent=0);

サンプルコードmetaconstructor.cppをコンパイルして、実行すると以下のような実行結果となります。

$ ./metaconstructor 
Foo() 0: Foo(0x50a320) 
Foo() 0: Foo(0x5109b0) 
Foo() 0: Foo(0x5109c0) 
Foo() 0: Foo(0x5107f0) 
Bar() 0: Bar(0x511fc0) 
Foo() 1: 10 Foo(0x510800) 
Foo() 1: 10 Foo(0x510810) 
Foo() 2: 100 10 Foo(0x512120) 
Foo() 2: 100 10 Foo(0x512180) 
$ 

サンプルコードを説明します。

リスト1 metaconstructor.cpp:
 1: #include <QtCore>
 2: 
 3: class Foo : public QObject
 4: {
 5:     Q_OBJECT
 6: 
 7: public:
 8:     Q_INVOKABLE explicit Foo(QObject* parent = 0) : QObject(parent) { 
 9:         qDebug() « "Foo() 0:" « this; 
10:     }
11:     Q_INVOKABLE explicit Foo(int arg1, QObject* parent = 0) : QObject(parent) { 
12:         qDebug() « "Foo() 1:" « arg1 « this; 
13:     }
14:     Q_INVOKABLE Foo(int arg1, int arg2, QObject* parent = 0) : QObject(parent) {
15:         qDebug() « "Foo() 2:" « arg1 « arg2 « this; 
16:     }
17: };
18: 
19: class Bar : public QObject
20: {
21:     Q_OBJECT
22: 
23: public:
24:     Q_INVOKABLE explicit Bar(QObject* parent = 0) : QObject(parent) { 
25:         qDebug() « "Bar() 0:" « this; 
26:     }
27:     Q_INVOKABLE explicit Bar(int arg1, QObject* parent = 0) : QObject(parent) { 
28:         qDebug() « "Bar() 1:" « arg1 « this; 
29:     }
30:     Q_INVOKABLE Bar(int arg1, int arg2, QObject* parent = 0) : QObject(parent) {
31:         qDebug() « "Bar() 2:" « arg1 « arg2 « this; 
32:     }
33: };

クラス Foo と Bar のコンストラクタに Q_INVOKABLE を付けて、コンストラクタを呼び出し可能にしています。

34: 
35: QObject* createObject(const QMetaObject* metaObject)
36: {
37:     return metaObject->newInstance();
38: }

どのクラスかは、判断せずにメタオブジェクトの newInstance() を呼び出しているだけですが、メタオブジェクトのクラスが異なれば、それに応じたインスタンスが作成されます。

39: 
40: int main(int argc, char** argv)
41: {
42:     QCoreApplication app(argc, argv);
43: 
44:     QObject* object = Foo::staticMetaObject.newInstance();

スタティックメタオブジェクトを直接アクセスして、newInstance()を呼び出してもFooインスタンスを生成できます。

45:     
46:     QGenericArgument parentArg = Q_ARG(QObject*, 0);
47:     object = Foo::staticMetaObject.newInstance(parentArg);                      // Returns Foo

親オブジェクトを指定するだけのコンストラクタ呼び出しです。

48: 
49:     const QMetaObject* metaObject = &Foo::staticMetaObject;
50:     object = metaObject->newInstance(parentArg);
51:     object = createObject(&Foo::staticMetaObject);                              // Returns Foo!
52:     object = createObject(&Bar::staticMetaObject);                              // Returns Bar!

createObject() に、このようにメタオブジェクトを渡してもクラスに対応したインスタンスが生成されます。

53:    
54:     QGenericArgument intArg1 = Q_ARG(int, 10);
55:     object = Foo::staticMetaObject.newInstance(intArg1, parentArg);             // Returns Foo
56:     object = metaObject->newInstance(intArg1, parentArg);                       // Returns Foo
57:     
58:     QGenericArgument intArg2 = Q_ARG(int, 100);
59:     object = Foo::staticMetaObject.newInstance(intArg2, intArg1, parentArg);    // Returns Foo
60:     object = metaObject->newInstance(intArg2, intArg1, parentArg);              // Returns Foo

引数を指定したコンストラクタ呼び出しです。

61: 
62:     return 0;
63: }
64: 
65: #include "metaconstructor.moc"

Q_SIGNAL と Q_SLOT

シグナルとスロットの宣言signalsとslotsに加えて、Q_SIGNALとQ_SLOTをメソッドの先頭に付ければ、シグナルとスロットを宣言できるようになりました。

Qt 4.6での宣言的ユーザインターフェース(Declarative UI)機能追加で、さらにオブジェクトシステムが変更されるでしょう。

おわりに

次回以降では、Qt 4.5で大きく変更されたQt Desinger、Qt Linguistについて説明します。

おすすめ記事

記事・ニュース一覧