サイトマップ
お知らせ、メモ
案内板
うちのヘッドライン
 




トップ  >  ソフトウェア豆知識  >  QGIS豆知識  >  QGIS API : C++アプリケーションを作成するには

QGIS API : C++アプリケーションを作成するには

QGISのCoding Compilation guideにはC++アプリケーションのシンプルなサンプルコードが記載されています。 以下のコードはCoding compilation guideからコードだけを抜き取ったものです。 コードについての詳細な説明は上記のドキュメントを参照してください。 なお、以下の例では、"C:/Program Files/qgis1.7.0"にQGISがインストールされているものとします。

   1: 
   2: //
   3: // QGIS Includes
   4: //
   5: #include <qgsapplication.h>
   6: #include <qgsproviderregistry.h>
   7: #include <qgssinglesymbolrenderer.h>
   8: #include <qgsmaplayerregistry.h>
   9: #include <qgsvectorlayer.h>
  10: #include <qgsmapcanvas.h>
  11: //
  12: // Qt Includes
  13: //
  14: #include <QString>
  15: #include <QApplication>
  16: #include <QWidget>
  17: 
  18: int main(int argc, char ** argv)
  19: {
  20: 	// Start the Application
  21: 	QgsApplication app(argc, argv, true);
  22:  
  23: 	QString myPluginsDir        = "C:/Program Files/qgis1.7.0/plugins";
  24: 	QString myLayerPath         = "C:/Data/testforest/test_forest.shp";
  25: 	QString myLayerBaseName     = "test_forest";
  26: 	QString myProviderName      = "ogr";
  27: 
  28: 	// Instantiate Provider Registry
  29: 	QgsProviderRegistry::instance(myPluginsDir);
  30: 	QgsVectorLayer * mypLayer = new QgsVectorLayer(myLayerPath, myLayerBaseName, myProviderName);
  31: 	QgsSingleSymbolRenderer *mypRenderer = new QgsSingleSymbolRenderer(mypLayer->geometryType());
  32: 	QList <QgsMapCanvasLayer> myLayerSet;
  33:  
  34: 	mypLayer->setRenderer(mypRenderer);
  35: 	if (mypLayer->isValid())
  36: 	{
  37: 		qDebug("Layer is valid");
  38: 	}
  39: 	else
  40: 	{
  41: 		qDebug("Layer is NOT valid");
  42: 	}
  43:  
  44: 	// Add the Vector Layer to the Layer Registry
  45: 	QgsMapLayerRegistry::instance()->addMapLayer(mypLayer, TRUE);
  46: 	// Add the Layer to the Layer Set
  47: 	myLayerSet.append(QgsMapCanvasLayer(mypLayer, TRUE));
  48:  
  49: 	// Create the Map Canvas
  50: 	QgsMapCanvas * mypMapCanvas = new QgsMapCanvas(0, 0);
  51: 	mypMapCanvas->setExtent(mypLayer->extent());
  52: 	mypMapCanvas->enableAntiAliasing(true);
  53: 	mypMapCanvas->setCanvasColor(QColor(0, 255, 255));
  54: 	mypMapCanvas->freeze(false);
  55: 	// Set the Map Canvas Layer Set
  56: 	mypMapCanvas->setLayerSet(myLayerSet);
  57: 	mypMapCanvas->setVisible(true);
  58: 	mypMapCanvas->refresh();
  59: 
  60: 	// Start the Application Event Loop
  61: 	return app.exec();
  62: }

このサンプルコードは一応正しく動作します。 ただし、このコードを実際に実行させるためには各コンパイラに対応した設定をあれこれ行う必要があります。 以下では、VC2010における設定について説明します。

VC2010のプロジェクト設定

まず、空の新規プロジェクトを作成します。プリコンパイル済みヘッダは使用しないほうが無難かと思います。

次にmain.cppを新規作成した後、コーディングする前にインクルードパスを設定します。 こうするとコードアシストが使えるようになるためです。 追加するインクルードパスは以下のとおりです。 Qtが"C:/"の直下にインストールされているものとします。

C:\Program Files\qgis1.7.0\include;
C:\Qt\4.7.1\include\QtCore;
C:\Qt\4.7.1\include\QtGui;
C:\Qt\4.7.1\include\QtXml;
C:\Qt\4.7.1\include

続いてプリプロセッサ定義を追加します。

WIN32;
DEBUG;
WINDOWS;
QT_GUI_LIB;
QT_CORE_LIB;
QT_DEBUG;_CRT_SECURE_NO_WARNINGS;
CRT_NONSTDC_NO_WARNINGS;
CORE_EXPORT=__declspec(dllimport);
GUI_EXPORT=__declspec(dllimport);
%(PreprocessorDefinitions)

重要なのは"CORE_EXPORT"、"GUI_EXPORT"の2つです。これらは全て __declspec(dllimport) を定義しています。 この定義は通常DLLのヘッダファイルにあったりすることが多いですが、QGISのライブラリでは定義されていないのでここで定義します。 なお、上記のコードを動作させるだけであればqgis_analysis.libはリンクしなくてもいいですが、analysis.libをリンクする必要がある場合は"ANALYSIS_EXPORT"の定義も追加します。

リンカの設定ではリンクするライブラリを指定します。 まず、追加のライブラリディレクトリを以下のように指定します。

c:\Qt\4.7.1\lib;
C:\Program Files\qgis1.7.0\lib;
%(AdditionalLibraryDirectories)

さらにリンクするライブラリを「追加の依存ファイル」に列挙します。

QtCored4.lib;
QtGuid4.lib;
QtXmld4.lib;
qtmaind.lib;
qgis_core.lib;
qgis_gui.lib;
%(AdditionalDependencies)

上記のうち、Qt関連はデバッグ版のインポートライブラリです。リリースビルドの場合はQtCore4.lib、QtGui4.lib、QtXml4.lib、qtmain.libをリンクしてください。 あと筆者のお勧めは、デバッグ版はコンソールが表示されるほうが qDebug() の出力を表示できるので、 デバッグ版はコンソールアプリケーション、リリース版はウィンドウアプリケーションと分けて設定する作戦です。 この場合、デバッグビルドの設定ではqtmaind.libは不要です。

上記のように設定するには[リンカー]-[システム]を選択し、サブシステムを変更します。 デバッグビルドではサブシステムをコンソールに、リリースビルドではWindowsにそれぞれ設定します。

あと、[構成プロパティ]-[全般]にある文字セットはUnicodeのままで大丈夫です。

これで一応設定が整いました。以下のように表示されれば一応成功です。

実行結果

メインウィンドウに表示

上記のプログラムは動作はしますがこれではどうしようもないので、キャンバスをウィジェットの1つとして取り扱えるようにしたいところです。 ここでは例としてQtのメインウィンドウアプリケーションにキャンバスを表示するようにしてみましょう。

まず、QtDesignerでメインウィンドウを作成します。 下の図はメインウィンドウにファイルを開くアクションを1つ作成したものです。 アクションにはスロットとしてonFileOpen()を割り当てました。

メインウィンドウのデザイン

次にcentralWidgetを格上げします。図のようにcentralwidgetを右クリックして「格上げ先を指定」を選択します。

格上げ先を指定

下図のように格上げされたクラス名をQgsMapCanvasとし、ヘッダファイルを"qgsmapcanvas.h"とします。 入力後【追加】ボタンを押し、さらに【格上げ】ボタンを押します。

格上げダイアログ

格上げ後はオブジェクトインスペクタには下図のように表示されます。

格上げ後

UIファイルができたら、VCプロジェクトに追加してカスタムビルドツールを定義し、生成されたヘッダファイルをVCプロジェクトに追加しましょう。 UIファイルに対するカスタムビルドツールの設定はここを参照してください。

あとは、前記のコードを適当な箇所に分配していきます。 まず、main関数は以下のようになります。

main.cpp
   1: 
   2: //
   3: // QGIS Includes
   4: //
   5: #include <qgsapplication.h>
   6: #include <qgsproviderregistry.h>
   7: //
   8: // Qt Includes
   9: //
  10: #include <QString>
  11: #include <QApplication>
  12: #include <QWidget>
  13: 
  14: #include "MyMainWindow.h"
  15: 
  16: int main(int argc, char ** argv)
  17: {
  18: 	QgsApplication app(argc, argv, true);
  19: 
  20: 	QString myPluginsDir        = "C:/Program Files/qgis1.7.0/plugins";
  21: 	QgsProviderRegistry::instance(myPluginsDir);
  22: 
  23: 	MyMainWindow window;
  24: 	window.show();
  25: 
  26: 	return app.exec();
  27: }

ずいぶんとすっきりしたものになりました。 main()関数内でメインウィンドウ表示以前に行っているのはプロバイダプラグインのパスの登録だけ(20~21行目)になっています。 メインウィンドウのクラス名はMyMainWindowとしています。

そのメインウィンドウクラスですが、まず宣言は以下のようにします。

MyMainWindow.h
   1: #pragma once
   2: 
   3: #include "ui_mainwindow.h"
   4: 
   5: class MyMainWindow :
   6: 	public QMainWindow, private Ui::MainWindow
   7: {
   8: 	Q_OBJECT
   9: 
  10: public:
  11: 	MyMainWindow(void);
  12: 	~MyMainWindow(void);
  13: 
  14: private slots:
  15: 	void onFileOpen();
  16: };
  17: 

先ほど作成したUIファイルのファイル名は"ui_mainwindow.h"として保存し、3行目でインクルードしています。 5~6行目のクラス宣言ではQMainWindowとUIクラスを多重継承しています。 多重継承が気に入らない場合は必須ではありませんが、そうするとdesignerで設定したシグナル/スロットは自分でコードする必要があります(大した手間ではありませんが)。

また、シグナル/スロットを利用するので、クラス宣言内にQ_OBJECTを記述する必要があります。 したがって、mocの作成も行う必要があります。 mocの作成についてはここを参照してください。

クラス定義部は以下のようにします。

MyMainWindow.cpp
   1: #include "MyMainWindow.h"
   2: #include <qgssinglesymbolrenderer.h>
   3: #include <qgsmaplayerregistry.h>
   4: #include <qgsvectorlayer.h>
   5: #include <QtGui>
   6: 
   7: MyMainWindow::MyMainWindow(void)
   8: {
   9: 	setupUi( this );
  10: 
  11: 	centralwidget->enableAntiAliasing(true);
  12: 	centralwidget->setCanvasColor(QColor(255, 192, 255));
  13: 	centralwidget->freeze(false);
  14: 	centralwidget->setVisible(true);
  15: }
  16: 
  17: 
  18: MyMainWindow::~MyMainWindow(void)
  19: {
  20: }
  21: 
  22: void MyMainWindow::onFileOpen()
  23: {
  24: 	QString strFName = QFileDialog::getOpenFileName( this, tr("File open"), "c:/", tr("Shape file (*.shp)" ) );
  25: 
  26: 	if ( !strFName.isEmpty() )
  27: 	{
  28: 		QgsVectorLayer * mypLayer = new QgsVectorLayer(strFName, QFileInfo(strFName).baseName(), "ogr" );
  29: 		QgsSingleSymbolRenderer *mypRenderer = new QgsSingleSymbolRenderer(mypLayer->geometryType());
  30: 		QList<QgsMapCanvasLayer> myLayerSet;
  31: 
  32: 		// Add the Vector Layer to the Layer Registry
  33: 		QgsMapLayerRegistry::instance()->addMapLayer(mypLayer, TRUE);
  34: 		// Add the Layer to the Layer Set
  35: 		myLayerSet.append(QgsMapCanvasLayer(mypLayer, TRUE));
  36: 
  37: 		centralwidget->setExtent(mypLayer->extent());
  38: 		centralwidget->setLayerSet(myLayerSet);
  39: 		centralwidget->refresh();
  40: 	}
  41: }

マップキャンバスの初期設定部分をコンストラクタ内に、またレイヤー登録・表示部をonFileOpen()内に記述しています。

以上でメインウィンドウアプリケーションの最低限の実装が完了しました。 実行すると以下のようになります。

実行結果

ここではキャンバスの色をピンキーにしてみました。

以上で最低限のアプリケーション実装は完了ですが、ズームイン・アウト、パンニングのマップツールはAPIで用意されているのでそれらの追加は簡単です。 また、ダイアログの一部としてキャンバスを貼り付けることももちろん可能です。

配布するには

配布するためには依存ライブラリを調べ上げて同梱する必要があろうかと思いますが、これが非常に大変です。 QGIS本体やコアライブラリだけでなく、一緒に配布するプロバイダプラグインが依存するライブラリも調べる必要があります。 最低でもgdalprovider.dll、ogrprovider.dllは同梱したいところで、 そうするとGDALが依存する膨大な量のライブラリを同梱する必要があるということになります。

Windows環境であればOSGeo4Wで大概はそろうかと思いますが、Linuxの場合は、、、。

とりあえず、WindowsであればDependency Walkerで、Linuxであればlddコマンドでこつこつ調べ上げましょう。


クリエイティブ・コモンズ・ライセンス
This documents by Yamate,N is licensed under a Creative Commons 表示 - 継承 3.0 非移植 License.
login