Tạo cập nhật lớp Qgis từ nguồn dữ liệu đã thay đổi


13

Tôi đang cố gắng để các lớp cập nhật tự động khi nguồn dữ liệu của chúng thay đổi. Tôi đang sử dụng R để viết một shapefile với một thuộc tính và tô màu theo thuộc tính đó trong QGIS.

Tôi muốn viết một shapefile mới với các giá trị thuộc tính khác nhau và cập nhật màu sắc bản đồ Qgis. Bước 1 đang kích hoạt quá trình đó, bước 2 là tạo lớp tải lại từ shapefile đã sửa đổi. Bước 2 của nó tôi đang lo lắng về đây.

Các câu hỏi / danh sách gửi thư khác đề cập đến việc sử dụng triggerRepainttrên lớp - không hoạt động. Các đề xuất khác bao gồm setCacheImage(None)và một lần nữa không hoạt động. Lớp cuối cùng sẽ cập nhật, nhưng tôi thực sự không thể thấy logic và đôi khi nó xảy ra một cách bất ngờ sau khi tôi không làm gì cả. Hoặc có lẽ tôi đã làm một cái gì đó hai phút trước.

Cách tái tạo để cập nhật nó là sao chép lớp từ menu chú thích - bản sao luôn lấy dữ liệu từ shapefile hiện tại và lớp gốc cũng tự cập nhật! Vì vậy, phải có một số cách làm nó.

Tôi nghĩ rằng nó đã hoạt động tốt hơn trong 2.8, nhưng đây là 2.10 nên có thể có một lỗi mới ở đâu đó.

Liên quan, nhưng không hoạt động với tôi trong 2.10:

Làm cách nào để tự động tải lại các lớp raster nếu nguồn được thay đổi trong QGIS?

Những thứ khác tôi đã thử:

  • layer.dataProvider().dataChanged.emit() - làm việc một lần, sau đó không lặp lại trên cùng một lớp

Tôi nghĩ rằng tôi đã theo dõi lý do tại sao sao chép lớp hoạt động - nếu tôi tạo một lớp ném mới dựa trên lớp được cập nhật và sau đó gọi .triggerRepaint()lớp được cập nhật, nó sẽ cập nhật trên khung bản đồ:

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

Nếu tôi sử dụng một nguồn lớp khác thì nó không hoạt động, vì vậy có vẻ như là nếu bạn tạo một đối tượng lớp dựa trên cùng một nguồn lớp ...

Một thử nghiệm nhanh ngay bây giờ với lớp raster (từ GeoTIFF) và chỉ cần gọi rlayer.triggerRepaint()có vẻ cập nhật đáng tin cậy chế độ xem của raster trong khung vẽ bản đồ.


Bạn có thể cần phải đăng một số mã mẫu.
Nathan W

@NathanW hầu hết những gì tôi đang làm là từ lớp gui - tải, tạo kiểu cho nó - sau đó nó chỉ lấy lớp và một vài dòng trong bảng điều khiển Python. Tôi không thích gắn cái này vào khuôn khổ của một plugin cho đến khi tôi biết tôi có thể làm cho nguyên tắc hoạt động! Tôi đã hy vọng sẽ có một câu trả lời nhanh chóng ("gọi layer.updateFromNewDataYouFool ()") nhưng tôi sẽ điền vào đây với nhiều mã hơn (bao gồm cả mã R để tạo các shapefiles) sau.
Spainedman

Để chắc chắn, bạn đã thử sử dụng cả hai lệnh sau đó: layer.setCacheImage(None)layer.triggerRepaint()?
Matthias Kuhn

Có @MatthiasKuhn - mặc dù đôi khi điều đó hoạt động, nhưng không thường xuyên. Tôi vừa viết một shapefile đã sửa đổi, đã làm cả hai điều đó trong bảng điều khiển Python (trên lớp bên phải), không có cập nhật trực quan. Điều đơn giản nhất đã hoạt động 100% cho đến nay là tạo ra một đối tượng lớp bỏ đi mới dựa trên nguồn lớp gốc như đã đề cập ở trên và sau đó triggerRepaint()trên lớp ban đầu. v 2.10.1-Pisa
Spainedman

Tôi có một nghi ngờ rằng điều này có thể liên quan đến việc giới thiệu nhóm kết nối OGR. Bạn có thể thực hiện một số kiểm tra nếu có sự khác biệt nếu bạn thay thế tệp trên đĩa hoặc chỉnh sửa tệp hiện có không?
Matthias Kuhn

Câu trả lời:


5

Điều này có liên quan đến việc giới thiệu nhóm kết nối OGR. [1]

Trước QGIS 2.10, một tệp đã được mở lại trên mỗi lần truy cập (ví dụ: sơn lại).

Vì QGIS 2.10, phần xử lý tệp được giữ mở và điều này có nghĩa là nếu một tệp được thay thế, phần xử lý vẫn trỏ đến tệp cũ trên các hệ thống dựa trên Unix.

QGIS 2.10: cách giải quyết

Thật không may, không có API để buộc QGIS mở lại tệp trong QGIS 2.10. Như một cách giải quyết, bạn có thể sử dụng một bản hack xấu xí:

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

QGIS 2.12: giải pháp

Tôi vừa giới thiệu một phương pháp mới sẽ có sẵn bắt đầu từ QGIS 2.12:

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

Cách tiếp cận chung

Nếu bạn có khả năng kiểm soát cách ghi đè tệp, bạn có thể mở các tệp hiện có với quyền ghi và thay đổi nội dung thay vì thay thế hoàn toàn các tệp (xóa / tạo lại) trên đĩa.

[1] Nhóm kết nối được giới thiệu để tăng tốc đáng kể quyền truy cập vào một số nguồn dữ liệu nhất định.


Trông giống như giải pháp tốt nhất. Việc .changeAttributeValuesđưa ra một "LRI 1: Cố gắng đọc hình dạng với id tính năng (-1) ngoài phạm vi khả dụng." nhưng nó ổn.
Spainedman

2

Nếu bạn xoay hoặc làm mới bản đồ, nó sẽ cập nhật.

Bài viết này nói rằng bạn có thể sử dụng những điều sau đây trong PyQGIS:

myLayer.triggerRepaint()

Để làm mới tất cả các lớp chức năng sau đây có thể được sử dụng:

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

Như tôi đã nói trong câu hỏi của mình, và như được đề cập trong liên kết tôi đã đưa ra, triggerRepaint()không hoạt động. refresh()trên bản đồ vải không hoạt động. Đặt hình ảnh bộ đệm thành None(hiện không dùng nữa trong tài liệu API) không hoạt động. Tôi vừa thử tất cả những thứ này trên một lớp shapefile mới được sửa đổi, mở bản đồ về, bật và tắt vis, nó không hoạt động. "Nhân đôi" lớp và nó cập nhật ngay lập tức. Bạn đã thử những thứ này cho mình (vào ngày 2.10) chưa?
Spainedman

Tôi nghĩ rằng chúng ta cần @ nathan-w để trả lời điều này. Tôi đã không thử nó ...
Alex Leith

Tôi đã thử trên #qgis trên IRC nhưng có lẽ tôi cần đăng lên danh sách gửi thư của qgis-dev ...
Spainedman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.