Buat pembaruan lapisan Qgis dari sumber data yang diubah

13

Saya mencoba untuk mendapatkan lapisan untuk diperbarui secara otomatis ketika sumber data mereka berubah. Saya menggunakan R untuk menulis shapefile dengan atribut, dan mewarnai sesuai dengan atribut itu di QGIS.

Saya ingin menulis shapefile baru dengan nilai atribut yang berbeda, dan perbarui warna peta Qgis. Langkah 1 memicu proses itu, langkah 2 membuat lapisan ulang dari shapefile yang dimodifikasi. Langkah 2 saya khawatir di sini.

Pertanyaan lain / obrolan milis menyebutkan menggunakan triggerRepaintpada lapisan - itu tidak berfungsi. Saran lain termasuk setCacheImage(None)dan sekali lagi itu tidak berhasil. Lapisan tidak memperbarui pada akhirnya, tetapi saya benar-benar tidak dapat melihat logikanya, dan kadang-kadang terjadi secara mengejutkan setelah saya tidak melakukan apa-apa. Atau mungkin saya melakukan sesuatu dua menit yang lalu.

Satu-satunya cara yang dapat direproduksi untuk memperbaruinya adalah dengan menduplikasi layer dari menu legenda - duplikat selalu mendapatkan datanya dari shapefile saat ini, dan layer asli juga memperbarui sendiri! Jadi pasti ada cara untuk melakukannya.

Saya pikir ini bekerja lebih baik di 2.8, tapi ini 2.10 jadi mungkin ada bug baru di suatu tempat.

Terkait, tetapi tidak berfungsi untuk saya di 2.10:

Bagaimana cara memuat ulang layer raster secara otomatis jika sumber diubah di QGIS?

Hal lain yang saya coba:

  • layer.dataProvider().dataChanged.emit() - Bekerja sekali, lalu tidak lagi pada lapisan yang sama

Saya pikir saya telah melacak mengapa menduplikasi lapisan berfungsi - jika saya membuat lapisan sekali pakai baru berdasarkan pada lapisan yang diperbarui dan kemudian memanggil .triggerRepaint()lapisan yang diperbarui, itu memperbarui pada kanvas peta:

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

Jika saya menggunakan sumber lapisan yang berbeda itu tidak berfungsi, jadi sepertinya jika Anda membuat objek lapisan berdasarkan sumber lapisan yang sama ...

Sebuah tes cepat sekarang dengan layer raster (dari GeoTIFF), dan hanya menelepon rlayer.triggerRepaint()tampaknya dapat memperbarui tampilan raster di kanvas peta.

Spacedman
sumber
Anda mungkin perlu memposting beberapa kode sampel.
Nathan W
@NathanW sebagian besar dari apa yang saya lakukan adalah dari gui - load layer, beri style - kemudian hanya mendapatkan layer dan beberapa baris di konsol Python. Saya enggan untuk menempel ini dalam kerangka plugin sampai saya tahu saya bisa membuat prinsip kerjanya! Saya berharap akan ada jawaban cepat ("panggil layer.updateFromNewDataYouFool ()") tetapi saya akan mengisi ini dengan lebih banyak kode (termasuk kode R untuk membuat shapefile) nanti.
Spacedman
Yang pasti, Anda mencoba menggunakan kedua perintah selanjutnya: layer.setCacheImage(None)dan layer.triggerRepaint()?
Matthias Kuhn
Ya @MatthiasKuhn - meskipun terkadang itu bekerja, tetapi tidak sering. Saya baru saja menulis sebuah shapefile yang dimodifikasi, melakukan kedua hal itu di konsol Python (di lapisan kanan), tidak ada pembaruan visual. Hal paling sederhana yang telah bekerja 100% sejauh ini adalah membuat objek layer throwaway baru berdasarkan sumber layer asli seperti yang disebutkan di atas dan kemudian triggerRepaint()pada layer asli. v 2.10.1-Pisa
Spacedman
Saya memiliki kecurigaan bahwa ini bisa terkait dengan pengenalan kumpulan koneksi OGR. Bisakah Anda melakukan beberapa tes jika ada perbedaan jika Anda mengganti file pada disk atau mengedit file yang ada?
Matthias Kuhn

Jawaban:

5

Ini terkait dengan pengenalan kumpulan koneksi OGR. [1]

Sebelum QGIS 2.10, file dibuka kembali pada setiap akses tunggal (misalnya pengecatan ulang).

Sejak QGIS 2.10 pegangan file tetap terbuka dan ini berarti jika file diganti pegangan masih menunjuk ke file lama pada sistem berbasis Unix.

QGIS 2.10: solusi

Sayangnya tidak ada API untuk memaksa QGIS untuk membuka kembali file di QGIS 2.10. Sebagai solusi, Anda dapat menggunakan peretasan yang buruk:

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

QGIS 2.12: solusi

Saya baru saja memperkenalkan metode baru yang akan tersedia mulai dari QGIS 2.12:

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

Pendekatan umum

Jika Anda memiliki kemungkinan untuk mengontrol bagaimana file ditimpa, Anda dapat membuka file yang ada dengan izin tulis dan mengubah konten alih-alih mengganti file sepenuhnya (hapus / buat kembali) pada disk.

[1] Kumpulan koneksi diperkenalkan untuk secara signifikan mempercepat akses ke sumber data tertentu.

Matthias Kuhn
sumber
Sepertinya solusi terbaik. The .changeAttributeValuesmembawa sebuah "ERROR 1: Mencoba untuk membaca bentuk dengan fitur id (-1) di luar jangkauan yang tersedia." tapi tidak apa-apa.
Spacedman
2

Jika Anda menggeser atau menyegarkan peta, peta itu harus diperbarui.

Artikel ini mengatakan bahwa Anda dapat menggunakan yang berikut ini di PyQGIS:

myLayer.triggerRepaint()

Untuk menyegarkan semua lapisan, fungsi berikut dapat digunakan:

def refresh_layers(self):
    for layer in qgis.utils.iface.mapCanvas().layers():
         layer.triggerRepaint()
Alex Leith
sumber
Seperti yang saya katakan dalam pertanyaan saya, dan seperti yang disebutkan dalam tautan yang saya berikan, triggerRepaint()tidak berhasil. refresh()pada kanvas peta tidak bekerja. Mengatur gambar cache ke None(yang sekarang tidak digunakan lagi dalam API API) tidak berfungsi. Saya baru saja mencoba semua hal ini pada layer shapefile yang baru dimodifikasi, menggeser peta tentang, matikan dan matikan, itu tidak berhasil. "Gandakan" layer dan itu memperbarui secara instan. Sudahkah Anda mencoba sendiri hal-hal ini (pada 2.10)?
Spacedman
Saya pikir kita perlu @ nathan-w untuk menjawab ini. Saya belum mencobanya sendiri ...
Alex Leith
Saya mencoba #qgis di IRC tapi mungkin saya perlu memposting ke milis qgis-dev ...
Spacedman