ทำการอัปเดตเลเยอร์ Qgis จากแหล่งข้อมูลที่เปลี่ยนแปลง


13

ฉันกำลังพยายามให้เลเยอร์อัปเดตโดยอัตโนมัติเมื่อแหล่งข้อมูลเปลี่ยนแปลง ฉันใช้ R เพื่อเขียน shapefile ด้วยแอตทริบิวต์และกำหนดสีตามคุณสมบัตินั้นใน QGIS

ฉันต้องการเขียน Shapefile ใหม่ที่มีค่าแอททริบิวต์ต่างกันและมีการอัพเดตสีแผนที่ Qgis ขั้นตอนที่ 1 เรียกกระบวนการนั้นขั้นตอนที่ 2 ทำให้การโหลดเลเยอร์ใหม่จาก Shapefile ที่แก้ไขแล้ว ขั้นตอนที่ 2 ฉันกังวลเกี่ยวกับที่นี่

การแช็ตรายการคำถาม / เมลอื่น ๆ ที่กล่าวถึงโดยใช้triggerRepaintในเลเยอร์ - ที่ไม่ทำงาน คำแนะนำอื่น ๆ ได้แก่setCacheImage(None)และอีกครั้งที่ไม่ได้ผล เลเยอร์จะอัปเดตในที่สุด แต่ฉันไม่เห็นตรรกะและบางครั้งมันเกิดขึ้นด้วยความประหลาดใจหลังจากฉันไม่ได้ทำอะไรเลย หรือบางทีฉันอาจจะทำอะไรบางอย่างเมื่อสองนาทีก่อน

วิธีหนึ่งที่ทำซ้ำได้ในการอัปเดตคือการทำซ้ำเลเยอร์จากเมนูคำอธิบาย - ที่ซ้ำกันจะได้รับข้อมูลจาก Shapefile ปัจจุบันและเลเยอร์ดั้งเดิมจะอัพเดตเองเช่นกัน! ดังนั้นจะต้องมีวิธีในการทำมัน

ฉันคิดว่ามันทำงานได้ดีขึ้นใน 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 ฉันไม่ชอบที่จะติดตั้งในกรอบของปลั๊กอินจนกว่าฉันจะรู้ว่าฉันสามารถทำให้หลักการทำงานได้! ฉันหวังว่าจะมีคำตอบอย่างรวดเร็ว ("call layer.updateFromNewDataYouFool ()") แต่ฉันจะกรอกข้อมูลนี้ด้วยรหัสเพิ่มเติม (รวมถึงรหัส R เพื่อสร้างรูปร่างไฟล์) ในภายหลัง
Spacedman

เพื่อให้แน่ใจว่าคุณลองใช้คำสั่งทั้งสองในภายหลัง: layer.setCacheImage(None)และlayer.triggerRepaint()?
Matthias Kuhn

ใช่ @MatthiasKuhn - แม้ว่าบางครั้งก็ใช้งานได้ แต่ไม่บ่อยนัก ฉันเพิ่งเขียน shapefile ที่แก้ไขแล้วทำทั้งสองอย่างนี้ในคอนโซล Python (ที่เลเยอร์ด้านขวา) ไม่มีการอัพเดตด้วยภาพ สิ่งที่ง่ายที่สุดที่ทำงานได้ 100% จนถึงขณะนี้คือการสร้างวัตถุเลเยอร์ใหม่ที่สร้างจากแหล่งเลเยอร์ดั้งเดิมตามที่กล่าวไว้ข้างต้นและจากtriggerRepaint()ชั้นเดิม v 2.10.1-Pisa
Spacedman

ฉันสงสัยว่าสิ่งนี้อาจเกี่ยวข้องกับการแนะนำพูลการเชื่อมต่อ OGR คุณสามารถทำการทดสอบบางอย่างได้ไหมถ้ามีความแตกต่างถ้าคุณแทนที่ไฟล์บนดิสก์หรือแก้ไขไฟล์ที่มีอยู่?
Matthias Kuhn

คำตอบ:


5

สิ่งนี้เกี่ยวข้องกับการแนะนำของพูลการเชื่อมต่อ OGR [1]

ก่อน QGIS 2.10 ไฟล์จะถูกเปิดอีกครั้งในทุกการเข้าถึง (เช่นทาสีใหม่)

ตั้งแต่ QGIS 2.10 หมายเลขอ้างอิงไฟล์จะถูกเปิดไว้และนี่หมายความว่าถ้าไฟล์ถูกแทนที่หมายเลขอ้างอิงยังคงชี้ไปที่ไฟล์เก่าบนระบบที่ใช้ Unix

QGIS 2.10: วิธีแก้ปัญหา

น่าเสียดายที่ไม่มี API ที่บังคับให้ QGIS เปิดไฟล์ใน QGIS 2.10 อีกครั้ง คุณสามารถใช้แฮ็คที่น่าเกลียดได้:

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

QGIS 2.12: วิธีแก้ปัญหา

ฉันเพิ่งแนะนำวิธีการใหม่ซึ่งจะเริ่มตั้งแต่ QGIS 2.12:

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

วิธีการทั่วไป

หากคุณมีความเป็นไปได้ที่จะควบคุมวิธีการเขียนทับไฟล์คุณสามารถเปิดไฟล์ที่มีอยู่ด้วยสิทธิ์การเขียนและเปลี่ยนเนื้อหาแทนการแทนที่ไฟล์ทั้งหมด (ลบ / สร้างใหม่) บนดิสก์

[1] กลุ่มการเชื่อมต่อได้รับการแนะนำเพื่อเพิ่มความเร็วในการเข้าถึงแหล่งข้อมูลบางอย่าง


ดูเหมือนทางออกที่ดีที่สุด .changeAttributeValuesนำขึ้น "ข้อผิดพลาด 1: พยายามที่จะอ่านรูปร่างที่มีคุณลักษณะประจำตัวประชาชน (-1) ออกจากช่วงที่มีอยู่." แต่ก็ไม่เป็นไร
Spacedman

2

หากคุณแพนหรือรีเฟรชแผนที่ควรอัพเดท

บทความนี้บอกว่าคุณสามารถใช้สิ่งต่อไปนี้ใน PyQGIS:

myLayer.triggerRepaint()

เพื่อรีเฟรชทุกเลเยอร์ต่อไปนี้สามารถใช้ฟังก์ชันได้

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

อย่างที่ฉันพูดในคำถามของฉันและตามที่กล่าวถึงในลิงก์ที่ฉันให้ไว้triggerRepaint()ไม่ทำงาน refresh()บนผืนผ้าใบแผนที่ไม่ทำงาน การตั้งค่าอิมเมจแคชเป็นNone(ซึ่งขณะนี้เลิกใช้แล้วในเอกสาร API) ไม่ทำงาน ฉันลองสิ่งเหล่านี้ทั้งหมดบนเลเยอร์ shapefile ที่เพิ่งปรับเปลี่ยนใหม่แพนแผนที่เกี่ยวกับสลับเปิดและปิดมันไม่ทำงาน "ซ้ำ" เลเยอร์และอัปเดตทันทีแม้ว่า คุณลองทำสิ่งเหล่านี้ด้วยตัวเอง (ใน 2.10)?
Spacedman

ฉันคิดว่าเราต้องการ @ nathan-w เพื่อตอบคำถามนี้ ฉันไม่ได้ลองด้วยตัวเอง ...
Alex Leith

ฉันลอง #qgis บน IRC แต่บางทีฉันอาจต้องโพสต์ไปยังรายชื่อผู้รับจดหมาย qgis-dev ...
Spacedman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.