はじめに
QtとWebKitを併用したアプリケーションでは、Qt/C++とHTMLドキュメントとの間を取り持つ機能が必要となります。QtからHTML内のデータへのアクセスするためにQWebFrame::evaluateJavaScript() を使用する方法を、前回説明しました。今回は、Webフォームへのアクセス方法やQtのウィジェットをHTML内で使う方法について説明します。また、10月末にTechnology PreviewがリリースされたQt/C++専用のIDEを簡単に紹介します。
Qt Creator
QtをIDEで使うには、Qt Eclipse Integration、Qt Visual Studio Integration、KDevelopという選択肢があります。そして、この10月末に、Windows、Linux、MacOS Xで使えるQt/C++専用のIDE Qt CreatorのTechnology Previewがリリースされました。
Qt Creatorは、Qt/C++で軽快にアプリケーションを作成できるようにすることを目的として作成されていて、Technical Previewでは以下の機能が用意されています。
- 編集機能
- C++用のエディタ
- ファイルとクラスのナビゲーション用ツール
- ヘルプシステムとの統合
- Qt Designerとの統合
- デバッグ機能
- GDBデバッガのグラフィカルフロントエンド
- QStringやQStringListなどのQtのクラスを解釈したオブジェクトの内容表示
- ビルドと実行
Qt Creatorは開発中のQt 4.5で作成されていますが、Qt 4.4.3のアプリケーションをQt Creatorで扱うこともできます。図1と図2は、その実行画面です。
正式リリース時期は2009年の第一四半期で、将来はリファクタリングツールも計画されいます。また、froglogic社のQt/C++の自動テストツールSquishもQt Softwareとの統合が検討されています。
Webフォームへのアクセス
Webフォームに入力された値をQt/C++から取得するサンプルコードForm ExtractorがQtの配布ソース中のexamples/webkit/formextractorにあり、Qt/C++のメソッドをHTMLから呼び出して入力値を参照しています。
図の左側はHTMLで記述された入力フォームです。右側はQtのウィジェットで、サブミット時にその入力値をWebフォームから取出して表示しています。図3、図4がサブミット前後の画面イメージです。
まず、HTMLの記述を説明しましょう。
27行目で、サブミット時にこの関数を呼び出すようにしています。
入力項目には以降のように、idをfirstname、lastname、genderMale、genderFemale、updatesにしているので、idから入力値を得ておきます。
formExtractorは、Qt/C++のオブジェクトがバインドされたJavaScriptオブジェクトで、setValues()は後述するQt/C++のFormExtractorクラスのスロットメソッドにバインディングされています。ここでsetValues()を呼び出すと、Qt/C++側のsetValues()が呼び出されて、Qt/C++側で入力値を得られることになります。
setValues()は、スロットですがQt/C++内ではシグナルから接続されていませんし、直接呼び出しもされていません。Qtのオブジェクトモデルの機能によって、JavaScriptから呼び出せるように実装されているスロットで、第3回で説明したQMetaObject::invokeMethod() を使って呼び出せるようにするために、スロットにしています。
シグナルQFrame::javaScriptWindowObjectCleared()が送信されるのは、URLをロードする前で、JavaScript環境のグローバルなウィンドウオブジェクトがクリアーされるときです。したがって、このシグナルが送信されるタイミングで、QWebFrame::addToJavaScriptWindowObject()を呼び出して、Qt/C++のオブジェクトをJavaScriptからアクセスできるようにすればよいことになります。
前述のように、JavaScriptから呼び出されるスロットで、Webフォームから渡されてきた値を図4の右側に表示しています。
このインスタンス自身をJavaScript環境のフレームのウィンドウオブジェクトに追加しています。このようにすることで、JavaScriptからQt/C++のFormExtractorのインスタンスのスロットを呼び出せるようになります。
Google Mapの例
図5のような、Google Mapで住所を表示するアプリケーションがQt Labs Blogsで紹介されています。
このアプリケーションについて説明しましょう。ソースコードはhttp://chaos.troll.no/~hhartz/addressbook.tarから入手できます。以降の説明では若干ソースコードを修正しています。
ジオコーディング
準備として、Google Maps APIを使うためにGoogle Maps APIのキーが必要です。キーは、Google Maps APIのページから取得できます。
まず、Google Mapsによって、住所から地理座標(緯度と経度)を求める部分を抜出して説明します。このプログラムは、以下のようにコマンドラインで指定した住所の緯度と経度を表示します。
QNetworkAccessManagerを使うと、URLを指定してネットワークリクエストを出し、その結果を得られます。結果が得られたときに送信されるシグナルfinished()に接続したスロットで、リクエストの結果を得て表示すればよいことになります。
ネットワークリクエストの結果を取得して処理が終わったときに送信するシグナルを定義します。
URI http://maps.google.com/maps/geo? に要求を送り、Google Maps APIジオコーダに直接アクセスして地理座標を取得します。URI に指定しているパラメータは以下のようになります。
q | 住所 |
output | 生成される出力の形式。xml、kml、csvまたはjsonの中から扱いやすいcsvを指定します。 |
key | 自分のGoogle Maps APIキー。Qt Labsの方のコードでは文字列"GOOGLE_MAPS_KEY"を自分のキーに書き換えて使います。 |
QNetworkReplyはQIODeviceを継承しているので、ファイルやソケットなどと同じように読み書きができます。readAll()で全結果を読込んでいます。結果はカンマ区切りで以下の値が返ってくるので、3番目と4番目を取り出せばよいことになります。
日本語の住所も扱えるように、QString::fromLocal8Bit()で変換してからAddr2Coord::geoCode()で地理座標を求めます。求め終わったらプログラムが終了するように、シグナルAddr2Coord::finished()をQApplication::quit() に接続しています。
地図の表示
図5の画面レイアウトはQt Designerで作成されていて、左側の住所の一覧にはQTreeViewが使われ、右側の地図にはQWebViewを継承したクラスMapが使われています。Mapではurlプロパティに以下のURLを指定して、世界地図が初期表示されるようにしています。
- http://chaos.troll.no/~hhartz/visualaccess/index.html
このURLの記述内容は、Google Maps APIキーの登録完了時に示されるHTML記述で、数ヵ所を変更してこのサンプルに合うようにしています。住所はファイルaddresses.txtに記述されていて、内容はリスト5のようになっています。カンマ区切りで2番目以降のフィールドが住所です。
この内容をQTreeViewに表示するために、リスト6でQStandardItemModelを継承したAddressModelを作成しています。
1番目のフィールドをQTreeViewに表示し、Qt::UserRoleに住所をデータとして格納しています。
ファイル全体を読み込んで、改行コードで分割してQStringのQListで返しています。日本語住所を扱えるようにするために、QString::fromUtf8()を元のコードに対して追加しています。
QTreeViewにAddressModelを設定して住所の一覧を表示させ、QTreeViewの項目をクリックしたら、showItem()スロットが呼び出されるようにしています。
先に説明したのと同様に、Map::geoCode()で住所を渡して、地図にマーカが表示されるようにしています。
得られた地理座標から地図上にマーカを表示し、センタリングをするために、QWebFrame::evaluateJavaScript()でJavaScriptのコードを実行しています。
Webコンテンツ内でのQtのウィジェットの利用
ここまでの説明で、Qt/C++でWebKitをどのように使うかが掴めたと思います。最後に、QtのウィジェットをWebフォームで使う方法について説明します。
図6は、Qt Labsで紹介されているQtWebKitを利用し、flickrの画像を検索して表示し、輝度やぼかしをクライアント側で行うサンプルです。このサンプルでは、QtのウィジェットをWebフォーム中で利用しているよい例です。このソースコードは、svn://labs.trolltech.com/svn/webkit/demo から入手できます。
Qtウィジェットの利用方法
Qt Labsのサンプルでは、CSSを使ったり、HTMLを切り換えてスタイルを指定したりといろいろなことをしているので、簡単なサンプルでQtのウィジェットをWebフォームで扱う方法についてのみ説明しましょう。図7は簡単なサンプル(リスト9)を実行したもので、説明文はHTMLで記述され、ウィジェットの配置もHTMLで行っています。
QtのウィジェットをHTML中で使うには、<OBJECT>タグを使います。classid属性は、使うウィジェットを識別するための名前です。
type属性には、application/x-qt-pluginまたはapplication/x-qt-styled-widgetを指定します。後者を指定すると、Qtのスタイルシートが使われるようになり、style属性でスタイルシートを指定できます。
widthやheightなどの属性は、Qtのウィジェットに対してsetProperty()を呼び出して、プロパティが設定されます。つまり、widthとheightでウィジェットの大きさを指定していることになります。
Webフォームで使う3つのウィジェットを用意しています。
HTML中の<OBJECT>タグのtype属性がapplication/x-qt-pluginかapplication/x-qt-styled-widget の場合に呼び出されるのでウィジェットのインスタンスを生成して返します。コンストラクタで生成したウィジェットを返すようにしていますが、新しくインスタンスを生成して返すこともできます。実際にQt Labsのサンプルでは、この部分はリスト11のようになっています。
コンストラクタで生成したものもcreatePlugin()で生成したもののどちらについても、ここで返しているインスタンスはQt側が不要になったときにメモリ解放をしているのでメモリリークは起きません。
まとめ
この特集では、Qtで実際にプログラミングするための基本的な機能、最新バージョンQt 4.4の機能と来年初頭のQt 4.5の予定機能、Qt 4.4で追加されたQt WebKitの基本的活用方法について説明しました。Qt WebKitは、Qt 4.5でWebKitをフルに利用できるようになり、QtとWebを融合させたいろいろなおもしろいアプリケーションが作れるようになるでしょう。なお、Qt Creatorについてはあらためてリリース時に詳しい解説を予定しています。