QGIS デザイナ

OSGeo4Wの中にqgisdesignerというものがいつの間にかありました。
これはQtDesgnerにQGISのウィジェットが追加されたものです。

QGISウィジェット

QGISウィジェット

なかなか便利そうなものがありますが、アプリケーションで使う場合は少しだけ手間がかかります。

ウィジェットに必要なリソースが参照できるようにする

ここにあるQGISウィジェットの一部はテーマの対象になっています。
したがって、アプリケーション側でテーマを利用するためのコードと、必要なアイコンなどのリソースが必要になります。
とりあえずテーマはdefaultでもいいとして、ウィジェットを利用するための準備は2通りあります。

リソースファイルに必要なアイコンを登録する

QgsApplication::defaultThemePath()関数は":/images/themes/default/"を返します。
テーマを何も設定していない場合はテーマアイコン類はここを参照して実行時に読み込まれます。
そこで、リソースファイルを用意して必要なアイコンを:/images/themes/default/に登録します。この方法はQGIS本体と同じものです。

カスタムコンフィグパスを設定する

リソースファイルを作らない場合の方法として、QgsApplicationのコンストラクタにカスタムコンフィグパスを引数として渡すというものがあります。
たとえば、実行ファイルから見て”../resources”以下に”themes/default”がある場合は、GetModuleFileName()
等で実行ファイルの位置を取得して、その文字列に”../resources”を連結し、それをコンストラクタに渡します。

   1: int main(int argc, char ** argv)
   2: {
   3:   char szDrv[_MAX_PATH+1], szDir[_MAX_PATH+1], szExePath[_MAX_PATH+1];
   4: 
   5:   ::GetModuleFileName( NULL, szExePath, _MAX_PATH );
   6:   ::_splitpath( szExePath, szDrv, szDir, NULL, NULL );
   7:   QString strConfigPath = QString(szDrv) + QString(szDir) + "../resources"
   8: 
   9:   QgsApplication app(argc, argv, true, strConfigPath );

バッチファイルから起動する場合は、環境変数としてバッチファイルの場所を記録しておいて、そこからたどる方法もあります。
たとえば、バッチファイルに以下のような記述をしておきます。

set OSGEO4W_ROOT=%~dp0

プログラム側ではこの文字列とバッチファイルからテーマまでの場所をつなげてQgsApplicationコンストラクタに渡します。

  QString strCustomConfigPath = qgetenv("OSGEO4W_ROOT") + "/resources";

  QgsApplication app(argc, argv, true, strCustomConfigPath );

必要なリソース

必要なリソースは以下のとおりです。他にもあるかもしれません。

ファイル名イメージ使用するウィジェット
mIconCollapse.pngmIconCollapse.pngQgsCollapsibleGroupBox
QgsExtentGroupBox
mIconDataDefine.svgmIconDataDefine.svgQgsDataDefinedButton
mIconDataDefineOn.svgmIconDataDefineOn.svg
mIconDataDefineError.svgmIconDataDefineError.svg
mIconDataDefineExpression.svgmIconDataDefineExpression.svg
mIconDataDefineExpressionOn.svgmIconDataDefineExpressionOn.svg
mIconDataDefineExpressionError.svgmIconDataDefineExpressionError.svg
mIconClear.svgmIconClear.svgQgsDateTimeEdit
QgsDoubleSpinBox
mIconExpression.svgmIconExpression.svgQgsFieldExpressionWidget
mActionSetProjection.svgmActionSetProjection.svgQgsProjectionSelectionWidget
mActionPropertyItem.pngmActionPropertyItem.pngQgsRelationReferenceWidget
mActionHighlightFeature.svgmActionHighlightFeature.svg
mActionScaleHighlightFeature.svgmActionScaleHighlightFeature.svg
mActionPanHighlightFeature.svgmActionPanHighlightFeature.svg
mActionRemove.svgmActionRemove.svg
mActionMapIdentification.svgmActionMapIdentification.svgQgsRelationReferenceWidget
QgsScaleRangeWidget
mActionZoomOut.svgmActionZoomOut.svgQgsScaleRangeWidget
mActionZoomIn.svgmActionZoomIn.svg
mIconFieldDate.svgmIconFieldDate.svgQgsFieldComboBox
QgsFieldExpressionWidget
mIconFieldDateTime.svgmIconFieldDateTime.svg
mIconFieldFloat.svgmIconFieldFloat.svg
mIconFieldInteger.svgmIconFieldInteger.svg
mIconFieldText.svgmIconFieldText.svg
mIconFieldTime.svgmIconFieldTime.svg
mIconLineLayer.svgmIconLineLayer.svgQgsMapLayerComboBox
mIconPointLayer.svgmIconPointLayer.svg
mIconPolygonLayer.svgmIconPolygonLayer.svg
mIconRasterLayer.svgmIconRasterLayer.svg
mIconTableLayer.svgmIconTableLayer.svg

使い方

以下では、とりあえず使い方が分かっているいくつかのウィジェットについて説明します。

QgsCollapsibleGroupBox

QGISに限らずに使いたいなかなかの優れものです。
左上のアイコンをクリックすると中身が閉じたり開いたりします。

開いているところ
閉じているところ

QgsCollapsibleGroupBoxの動作

スクロールエリアなどのパネルと同様に、パネルの中にレイアウトを設定しないと正しく動作しません

QgsExpressionBuilderWidget

式ビルダのウィジェットです。

QgsExpressionBuilderWidget

QgsExpressionBuilderWidget

以下のコードはウィジェットの初期化です。
本体QGISのコードを参考にしています。スコープ等今一つよくわからないところも多いです。

   1:   mExpressionBuilderWidget->setLayer( pLayer );
   2:   mExpressionBuilderWidget->loadFieldNames();
   3: 
   4:   QgsExpressionContext context;
   5:   context << QgsExpressionContextUtils::globalScope()
   6:   << QgsExpressionContextUtils::projectScope()
   7:   << QgsExpressionContextUtils::layerScope( pLayer );
   8:   mExpressionBuilderWidget->setExpressionContext( context );
   9: 
  10:   QgsDistanceArea myDa;
  11:   QgsMapCanvas *pCanvas = dynamic_cast<MyMainWindow *>(m_pParent)->mapCanvas();
  12:   myDa.setSourceCrs( pLayer->crs().srsid() );
  13:   myDa.setEllipsoidalMode( pCanvas->mapSettings().hasCrsTransformEnabled() );
  14:   myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
  15:   mExpressionBuilderWidget->setGeomCalculator( myDa );
  16: 
  17:   QObject::connect( mExpressionBuilderWidget, SIGNAL(expressionParsed (bool)), m_pParent, SLOT(setSubset(bool)) );

ベクタレイヤのポインタを渡すことで、式ビルダ内のオペランドにベクタレイヤのフィールドを使用することができるようになります。
17行目では、式ビルダが発行するexpressionParsedシグナルをスロットにつなげています。
このシグナルは入力された式が正当になったときに発行されるので、このシグナルとキャンバス描画変更のスロットをつなげることで式ビルダの式の変更が即座にキャンバスに反映されるようにすることができます。

典型的な使い方はベクタレイヤのフィルタに式の文字列を使用するというものではないでしょうか。
式ビルダの式はexpressionText()関数で取得します。

上記17行目のスロットの例
   1: void MyMainWindow::setSubset( bool bValid )
   2: {
   3:   if ( bValid )
   4:   {
   5:     QgsVectorLayer *pLayer = dynamic_cast<QgsVectorLayer *>( centralwidget->layer( 0 ) );
   6:     pLayer->setSubsetString( m_pDlg->mExpressionBuilderWidget->expressionText() );
   7:     centralwidget->refresh();
   8:   }
   9: }
  10: 

QgsExtentGroupBox

キャンバス表示範囲やレイヤの範囲等の情報を表示するウィジェットです。
QgsCollapsibleGroupBox上で作られているので折りたたむことができます。

QgsExtentGroupBox

QgsExtentGroupBox

単にセットした範囲の座標を表示するだけでなく、座標変換も行ってくれるなかなかの優れものです。
座標変換ができるようにするためにはsetOutputCrs()を呼び出して出力CRSを設定する必要があります。

   1:   QgsCoordinateReferenceSystem crsDst;
   2:   crsDst.createFromSrid( 4612 );
   3:   mExtentGroupBox->setCurrentExtent( pCanvas->extent(), pLayer->crs() );
   4:   mExtentGroupBox->setOriginalExtent( pLayer->extent(), pLayer->crs() );
   5:   mExtentGroupBox->setOutputCrs( crsDst );

計算後の範囲の座標を取得するにはoutputExtent()関数を呼び出します。

QgsFieldComboBox

ベクタレイヤの属性一覧を表示するウィジェットです。
mFieldComboBox->setLayer( pLayer )でレイヤをセットするとそのレイヤのフィールド一覧がデータ型のアイコンとともに表示されます。

選択されているフィールドを取得するにはcurrentField()関数を呼び出します。戻り値はQString型です。

QgsFieldComboBox

QgsFieldComboBox

QgsFieldExpressionWidget

QgsFieldComboBoxに式ビルダを起動するアイコンがついたものです。
加えて、ここに入力された式の正当性の評価も行ってくれます。
使用するには、QgsFieldComboBoxと同様にsetLayer()関数を使用します。

フィールドのみを取得するにはcurrentField()関数を、
現在の式を取得するにはcurrentText()またはasExpression()関数を呼び出します
(asExpression()は、式の場合はcurrentTexxt()と同じで、フィールドの場合はダブルクォートで囲んで返す)。
戻り値はいずれもQString型です。

QgsFieldExpressionWidget

QgsFieldExpressionWidget

QgsMapLayerComboBox

現在ロードされているレイヤの一覧を表示するウィジェットです。
レイヤのリストはQgsMapLayerRegistryインスタンスから取ってくるので、構築時にユーザは何もする必要がありませんが、
リストに表示しないレイヤやフィルタを設定することもできます。

選択されているレイヤはcurrentLayer()で取得することができます。

QgsMapLayerComboBox

QgsMapLayerComboBox

QgsProjectionSelectionWidget

CRSを選択するウィジェットです。
選択されたCRSはcrs()関数で取得します。
戻り値はQgsCoordinateReferenceSystem型なので使いやすいです。

QgsProjectionSelectionWidget

QgsProjectionSelectionWidget

QgsScalewidget

縮尺を選択するウィジェットです。
縮尺はあらかじめ登録されており、構築時にユーザは何もする必要がありませんが、
マップキャンバスのポインタを渡すと現在のマップキャンバスの縮尺が表示されます。

選択されている縮尺を取得するにはscale()またはscaleString()を呼び出します。

QgsScalewidget

QgsScalewidget

QgsScaleRangeWidget

表示条件で縮尺を指定するときに出てくるウィジェットです。
QgsScalewidgetが2つ配置されています。

縮尺を取得するには、
maximumScale()
minimumScale()
maximumScaleDenom()
minimumScaleDenom()
等の可数を使用します。

QgsScaleRangeWidget

QgsScaleRangeWidget
アーカイブ