基本的には、選択範囲のQgsRectangle
を作って、プロバイダのselect
を呼び出して選択します。
v2.4あたりからか、選択方法に変更があったようです。(下記参照)
なお、以下の例ではキャンバスのオンザフライが無効の場合の例です。
有効になっている場合は、マウスカーソルや枠の座標変換が必要になります。
1クリックで選択の場合
以下の例はクリックした地点周辺の要素をWKT形式で表示する例です。
キャンバスクリックイベントの引数がピクセル単位なのに注意。
class SelectTool(QgsMapTool): def canvasPressEvent(self, event): layer = self.canvas().currentLayer() if ( layer.type() != QgsMapLayer.VectorLayer ): return provider = layer.dataProvider() ll = self.toMapCoordinates(QPoint(event.pos().x()-5, event.pos().y()-5)) ur = self.toMapCoordinates(QPoint(event.pos().x()+5, event.pos().y()+5)) rect = QgsRectangle(ll, ur) # 前はこうだった...ハズ provider.select([], rect, True, True) # 最近のバージョンならこれでOK # 第2引数はTrueなら現在の選択に追加 layer.select(rect, True) str = QString() feat = QgsFeature() while provider.nextFeature(feat): str += feat.geometry().exportToWkt() QMessageBox.information(None, "Coordinates", str)
スウィープセレクト
マウスをドラッグして選択する場合も、ドラッグ開始-終了の矩形を使って上記のように選択すれば良いですが、
できればドラッグ時の範囲を描画したいところです。
で、こういうときに便利なのがQgsRubberBand
クラスで(たしか、v1.5かv1.6で追加された)、
これは矩形に限らず連続線分や多角形などの一時的描画に利用するクラスです。
これを使って、スウィープセレクトを実装したのが以下の例です。
QgsRubberBand
クラスへの点の追加方法はほかにもあるので、これが最良かどうかは怪しいです。
class SweepSelectTool(QgsMapTool): def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.canvas = canvas self.rubberBand = QgsRubberBand(canvas, True) self.pressed = False def canvasPressEvent(self, event): ll = self.toMapCoordinates(QPoint(event.pos().x(), event.pos().y())) self.rubberBand.addPoint(ll, False) self.rubberBand.addPoint(ll, False) self.rubberBand.addPoint(ll, False) self.rubberBand.addPoint(ll, True) self.pressed = True def canvasMoveEvent(self, event): if self.pressed == True: ll = self.rubberBand.getPoint(0) ur = self.toMapCoordinates(QPoint(event.pos().x(), event.pos().y())) self.rubberBand.movePoint(1, QgsPoint(ll.x(), ur.y())) self.rubberBand.movePoint(2, ur) self.rubberBand.movePoint(3, QgsPoint(ur.x(), ll.y())) def canvasReleaseEvent(self, event): layer = self.canvas.currentLayer() if layer == None or layer.type() != QgsMapLayer.VectorLayer: self.rubberBand.reset() self.pressed = False return # 前はこうだった...ハズ provider = layer.dataProvider() provider.select([], self.rubberBand.asGeometry().boundingBox(), True, True) # 最近のバージョンならこれでOK # 第2引数はTrueなら現在の選択に追加 layer.select(self.rubberBand.asGeometry().boundingBox(), True) str = QString() feat = QgsFeature() while provider.nextFeature(feat): str += feat.geometry().exportToWkt() QMessageBox.information(None, "Coordinates", str) self.rubberBand.reset() self.pressed = False
QGIS2.4?から選択の方法が変わったようです。QgsFeatureRequestクラスを使うようになったようです。
v2.4以降の場合(C++コード)
QgsFeature feat; QgsFeatureIterator pIter = pqvlPointLayer->getFeatures( QgsFeatureRequest(rcSelect) ); while ( pIter.nextFeature( feat ) ) { features.append( feat ); }
要素番号を指定する場合
選択する要素を要素の番号で指定したい場合は以下のようにすることもできます。
layer.modifySelection([0,1], [])
第1引数が選択する要素番号で、第2引数は選択を解除する要素番号です。