変更されたデータソースからQgisレイヤーを更新する


13

データソースが変更されたときにレイヤーを自動的に更新しようとしています。Rを使用して属性を持つシェープファイルを作成し、QGISでその属性に応じて色付けしています。

さまざまな属性値を使用して新しいシェープファイルを作成し、Qgisマップの色を更新します。ステップ1はそのプロセスをトリガーし、ステップ2は変更されたシェープファイルからレイヤーをリロードします。そのステップ2ここで心配しています。

他の質問/メーリングリストのチャット担当者はtriggerRepaint、レイヤーでの使用について言及しています-それは機能しません。その他の提案にはsetCacheImage(None)、これも機能しません。レイヤーは最終的に更新されますが、実際にはロジックを見ることができず、何もしなかった後に時々驚かされます。または、2分前に何かをしたかもしれません。

更新できるようにする再現可能な方法の1つは、凡例メニューからレイヤーを複製することです。複製は常に現在のシェープファイルからデータを取得し、元のレイヤーも更新されます。そのため、何らかの方法が必要です。

2.8ではうまく機能していたと思いますが、これは2.10なので、どこかに新しいバグがあるかもしれません。

関連するが、2.10では機能しない:

QGISでソースが変更された場合、ラスターレイヤーを自動的に再読み込みする方法は?

私が試した他のこと:

  • layer.dataProvider().dataChanged.emit() -一度作業した後、同じレイヤーで再び作業しなかった

レイヤーの複製が機能する理由を追跡したと思います-更新されたレイヤーに基づいて新しい使い捨てレイヤーを作成し、更新されたレイヤーを呼び出すと.triggerRepaint()、マップキャンバスで更新されます:

QgsVectorLayer( layer.source(), "layer copy", layer.providerType() )
layer.triggerRepaint()

別のレイヤーソースを使用すると動作しません。そのため、同じレイヤーソースに基づいてレイヤーオブジェクトを作成すると思われます...

ラスターレイヤー(GeoTIFFから)を使用した簡単なテストと、呼び出しだけrlayer.triggerRepaint()で、マップキャンバスのラスターのビューを確実に更新するようです。


サンプルコードを投稿する必要がある場合があります。
ネイサンW

@NathanW私がやっていることのほとんどは、GUIからです-レイヤーをロードし、スタイルを設定します-そして、レイヤーとPythonコンソールのそれらの数行を取得します。私は、原則をうまく機能させることができるとわかるまで、これをプラグインのフレームワークに固執することに気が進まない!簡単な回答(「layer.updateFromNewDataYouFool()を呼び出す」)があればいいのにと思っていましたが、後でもっと多くのコード(シェープファイルを作成するRコードを含む)で埋めます。
Spacedman

確かに、その後両方のコマンドを使用してみました:layer.setCacheImage(None)およびlayer.triggerRepaint()
マティアスクーン

はい@MatthiasKuhn- 時々それは動作しますが、頻繁ではありません。修正されたシェープファイルを作成し、Pythonコンソール(右のレイヤー)でこれらの両方を行いましたが、視覚的な更新は行いませんでした。これまで100%で機能してきた最も簡単なことは、上記の元のレイヤーソースと元のレイヤーに基づいて、新しい使い捨てレイヤーオブジェクトを作成することtriggerRepaint()です。v 2.10.1-ピサ
Spacedman

これはOGR接続プールの導入に関連しているのではないかと疑っています。ディスク上のファイルを置き換えるか、既存のファイルを編集する場合に違いがある場合、いくつかのテストを実行できますか?
マティアスクーン

回答:


5

これは、OGR接続プールの導入に関連しています。[1]

QGIS 2.10より前は、ファイルはすべての単一アクセスで再オープンされました(再ペイントなど)。

QGIS 2.10以降、ファイルハンドルは開いたままになります。これは、ファイルが置き換えられ場合でも、Unixベースのシステム上の古いファイル指すことを意味します。

QGIS 2.10:回避策

残念ながら、QGISにQGIS 2.10でファイルを再度開かせるAPIがありません。回避策として、いハックを使用できます。

layer.dataProvider().changeAttributeValues( { -1: { 0: 0 } } )
layer.triggerRepaint()

QGIS 2.12:ソリューション

私はちょうど新しい方法を導入 QGIS 2.12から始まって利用できるようになります:

layer.dataProvider().forceReload()
layer.triggerRepaint()

一般的方法

ファイルの上書き方法を制御する可能性がある場合は、ディスク上のファイルを完全に置換(削除/再作成)する代わりに、書き込み権限で既存のファイルを開いて内容を変更できます。

[1]接続プールは、特定のデータソースへのアクセスを大幅に高速化するために導入されました。


最適なソリューションのように見えます。.changeAttributeValues「ERROR 1:利用可能範囲外のフィーチャID(-1)と形状を読み取ろうとする」を起動します でも大丈夫です
Spacedman

2

マップをパンまたは更新すると、マップが更新されます。

この記事では、PyQGISで以下を使用できると述べています。

myLayer.triggerRepaint()

すべてのレイヤーを更新するには、次の機能を使用できます。

def refresh_layers(self):
    for layer in qgis.utils.iface.mapCanvas().layers():
         layer.triggerRepaint()

私が私の質問で言ったように、そして私が与えたリンクで述べたように、triggerRepaint()機能しません。refresh()マップキャンバスでは機能しません。キャッシュイメージをNone(APIドキュメントで非推奨になった)に設定しても機能しません。新しく変更したシェープファイルレイヤーでこれらすべてを試し、マップをパンし、visのオンとオフを切り替えましたが、機能しませんでした。レイヤーを「複製」するとすぐに更新されます。これらのことを自分で試しましたか(2.10)?
Spacedman

これに答えるには@ nathan-wが必要だと思います。私自身は...それを試していない
アレックス・リース

IRCで#qgisを試しましたが、おそらくqgis-devメーリングリストに投稿する必要があります...
Spacedman
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.