OSGeo4Wの中にqgisdesignerというものがいつの間にかありました。
これはQtDesgnerに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.png | QgsCollapsibleGroupBox QgsExtentGroupBox | |
mIconDataDefine.svg | QgsDataDefinedButton | |
mIconDataDefineOn.svg | ||
mIconDataDefineError.svg | ||
mIconDataDefineExpression.svg | ||
mIconDataDefineExpressionOn.svg | ||
mIconDataDefineExpressionError.svg | ||
mIconClear.svg | QgsDateTimeEdit QgsDoubleSpinBox | |
mIconExpression.svg | QgsFieldExpressionWidget | |
mActionSetProjection.svg | QgsProjectionSelectionWidget | |
mActionPropertyItem.png | QgsRelationReferenceWidget | |
mActionHighlightFeature.svg | ||
mActionScaleHighlightFeature.svg | ||
mActionPanHighlightFeature.svg | ||
mActionRemove.svg | ||
mActionMapIdentification.svg | QgsRelationReferenceWidget QgsScaleRangeWidget | |
mActionZoomOut.svg | QgsScaleRangeWidget | |
mActionZoomIn.svg | ||
mIconFieldDate.svg | QgsFieldComboBox QgsFieldExpressionWidget | |
mIconFieldDateTime.svg | ||
mIconFieldFloat.svg | ||
mIconFieldInteger.svg | ||
mIconFieldText.svg | ||
mIconFieldTime.svg | ||
mIconLineLayer.svg | QgsMapLayerComboBox | |
mIconPointLayer.svg | ||
mIconPolygonLayer.svg | ||
mIconRasterLayer.svg | ||
mIconTableLayer.svg |
使い方
以下では、とりあえず使い方が分かっているいくつかのウィジェットについて説明します。
QgsCollapsibleGroupBox
QGISに限らずに使いたいなかなかの優れものです。
左上のアイコンをクリックすると中身が閉じたり開いたりします。
QgsCollapsibleGroupBoxの動作
スクロールエリアなどのパネルと同様に、パネルの中にレイアウトを設定しないと正しく動作しません
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
単にセットした範囲の座標を表示するだけでなく、座標変換も行ってくれるなかなかの優れものです。
座標変換ができるようにするためには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
QgsFieldExpressionWidget
QgsFieldComboBoxに式ビルダを起動するアイコンがついたものです。
加えて、ここに入力された式の正当性の評価も行ってくれます。
使用するには、QgsFieldComboBoxと同様にsetLayer()
関数を使用します。
フィールドのみを取得するにはcurrentField()
関数を、
現在の式を取得するにはcurrentText()
またはasExpression()
関数を呼び出します
(asExpression()は、式の場合はcurrentTexxt()
と同じで、フィールドの場合はダブルクォートで囲んで返す)。
戻り値はいずれもQString
型です。
QgsFieldExpressionWidget
QgsMapLayerComboBox
現在ロードされているレイヤの一覧を表示するウィジェットです。
レイヤのリストはQgsMapLayerRegistry
インスタンスから取ってくるので、構築時にユーザは何もする必要がありませんが、
リストに表示しないレイヤやフィルタを設定することもできます。
選択されているレイヤはcurrentLayer()
で取得することができます。
QgsMapLayerComboBox
QgsProjectionSelectionWidget
CRSを選択するウィジェットです。
選択されたCRSはcrs()
関数で取得します。
戻り値はQgsCoordinateReferenceSystem
型なので使いやすいです。
QgsProjectionSelectionWidget
QgsScalewidget
縮尺を選択するウィジェットです。
縮尺はあらかじめ登録されており、構築時にユーザは何もする必要がありませんが、
マップキャンバスのポインタを渡すと現在のマップキャンバスの縮尺が表示されます。
選択されている縮尺を取得するにはscale()
またはscaleString()
を呼び出します。
QgsScalewidget
QgsScaleRangeWidget
表示条件で縮尺を指定するときに出てくるウィジェットです。
QgsScalewidget
が2つ配置されています。
縮尺を取得するには、
maximumScale()
、
minimumScale()
、
maximumScaleDenom()
、
minimumScaleDenom()
、
等の可数を使用します。