Làm cách nào để tôi có thể tạo và thêm các tính năng vào lớp bộ nhớ trong QGIS 1.9 theo cách lập trình?


13

Tôi đã có một plugin hoạt động trong QGIS 1.8 để đọc dữ liệu từ cơ sở dữ liệu MSAccess và thêm nó vào một loạt các lớp bộ nhớ. Có một số xử lý liên quan đến tạm thời vì vậy tôi không nghĩ đơn giản sử dụng QGIS để đọc trực tiếp từ cơ sở dữ liệu là một tùy chọn.

Tôi muốn chuyển từ QGIS 1.8 sang 1.9 (chủ yếu là do chất lượng của trình soạn thảo in được cải thiện). Plugin không hoạt động với API mới.

Tôi đã thử nhiều phương pháp khác nhau trong các tìm kiếm của google. Một, sửa đổi mã dưới đây - từ http://www.qgis.org/pyqgis-cookbook/vector.html#memory-provider , tức là thêm hình học và thuộc tính vào dataprovider và sau đó cập nhật lớp - để phù hợp với API mới hoạt động một chút nhưng các thuộc tính không thể nhìn thấy cho đến khi tôi nhập vào chế độ chỉnh sửa (tương tự như http://hub.qgis.org/issues/3713 ). Một cách tiếp cận khác, chi tiết trong câu trả lời số 1 của liên kết trên, đã thêm chính xác lớp và thuộc tính nhưng tôi không thể thêm các tính năng cho lớp.

Cho rằng đó là một nhiệm vụ khá đơn giản, tôi hy vọng rằng ai đó ở đây có thể đưa ra một ví dụ hoạt động về cách thực hiện việc này. (PS Tôi không phải là một lập trình viên chuyên nghiệp và hầu hết mã hóa của tôi khá thô sơ - Tôi hoan nghênh mọi hướng dẫn nhưng yêu cầu bạn tha thứ cho sự thiếu hiểu biết từ phía tôi)

# Receivers = a list of lists returned from a database query

# create layer
vl = QgsVectorLayer("Point", item, "memory")
pr = vl.dataProvider()

# add fields
pr.addAttributes( [ QgsField("Rec_No", QVariant.Int), QgsField("Include",  QVariant.String), QgsField("Label",  QVariant.String), QgsField("X", QVariant.Double),
                    QgsField("Y", QVariant.Double), QgsField("Z", QVariant.Double), QgsField("Height", QVariant.Double),
                    QgsField("Project_Re", QVariant.String), QgsField("NCA", QVariant.String),
                    QgsField("DayCrit", QVariant.Int), QgsField("EveCrit", QVariant.Int), QgsField("NightCrit", QVariant.Int) ] )

for i in range(len(Receivers)):          
  # add a feature
  fet = QgsFeature()
  X = Receivers[i][3]
  Y = Receivers[i][4]
  fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )

  # Details = a list of results returned from a database query specific to each result in 'Receivers'

  if Receivers[i][3] != 0:
    Include = 'Yes'
  else:
    Include = 'No'

  fet.setAttributeMap( { 0 : QVariant(Receivers[i][0]), 1 : QVariant(Include), 2 : QVariant(Receivers[i][2]),
                         3 : QVariant(Receivers[i][3]), 4 : QVariant(Receivers[i][4]), 5 : QVariant(Receivers[i][5]), 6 : QVariant(Receivers[i][6]),
                         7 : QVariant(Details[0]), 8 : QVariant(Details[1]), 9 : QVariant(Details[2]), 10 : QVariant(Details[3]), 11 : QVariant(Details[4]) } )
  pr.addFeatures( [ fet ] )

# add a style
vl.loadNamedStyle('C:/OSGeo4W/apps/qgis/python/plugins/Gopher2QGIS/styles/Receiver_Style.qml')

# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.commitChanges()
vl.updateExtents()
vl.updateFieldMap()

QgsMapLayerRegistry.instance().addMapLayer(vl)

Hãy xem plugin PinPoint. Nó bổ sung các tính năng với các thuộc tính cho lớp bộ nhớ và hoạt động với API 2.0.
gsherman

Rất tốt, hoạt động như một nét duyên dáng. Tôi đã sử dụng ví dụ này để thêm một lớp với các điểm từ dịch vụ restfull. QGis thật tuyệt
Peter Venema

Câu trả lời:


8

Nhờ gsherman ở trên ví dụ plugin PinPoint là hoàn hảo.

Theo tôi hiểu thì quá trình này là:

  1. Tạo lớp với các thuộc tính trong chuỗi xây dựng
  2. Thêm lớp đã nói vào sổ đăng ký bản đồ
  3. Bắt đầu chỉnh sửa trên lớp đó
  4. Thêm tính năng và cam kết thay đổi

Đây là một trích xuất mã của tôi hiện đang hoạt động.

layer =  QgsVectorLayer(
          "Point?field=Rec_No:integer&field=Include:string(120)&field=Label:string(120)&field=X:double&field=Y:double&field=Z:double&field=Height:double&field=Project_Re:string(120)&field=NCA:string(120)&field=DayCrit:integer&field=EveCrit:integer&field=NightCrit:integer",
          item,
          "memory")
QgsMapLayerRegistry.instance().addMapLayer(layer)

# Receivers = as in the above example 'Receivers' is a list of results
for i in range(len(Receivers)):

  # add a feature
  feature = QgsFeature()

  X = Receivers[i][3]
  Y = Receivers[i][4]
  feature.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )

  # Details = as in the above example 'Details' is a list of results

  if Receivers[i][1] != 0:
    Include = 'Yes'
  else:
    Include = 'No'

  values = [ QVariant(Receivers[i][0]), QVariant(Include), QVariant(Receivers[i][2]),
                         QVariant(Receivers[i][3]), QVariant(Receivers[i][4]), QVariant(Receivers[i][5]), QVariant(Receivers[i][6]),
                         QVariant(Details[0]), QVariant(Details[1]), QVariant(Details[2]), QVariant(Details[3]), QVariant(Details[4]) ]

  feature.setAttributes(values)
  layer.startEditing()
  layer.addFeature(feature, True)
  layer.commitChanges()

6

Dựa trên câu trả lời của Adam Bioletti, các thử nghiệm tiếp theo cho quy trình được mô tả cho thấy yêu cầu thiết yếu duy nhất là bắt đầu chỉnh sửa lớp bộ nhớ trước khi thực hiện bất kỳ thay đổi nào, chẳng hạn như tạo thuộc tính và tính năng, sau đó cam kết thay đổi. Điều này có thể được thực hiện trước khi thêm lớp vào bản đồ đăng ký.

Đây là bản cập nhật mã của Cookbook hoạt động với API 2.0:

# create layer
vl = QgsVectorLayer("Point", "temporary_points", "memory")
pr = vl.dataProvider()

# changes are only possible when editing the layer
vl.startEditing()
# add fields
pr.addAttributes([QgsField("name", QVariant.String),QgsField("age", QVariant.Int),QgsField("size", QVariant.Double)])

# add a feature
fet = QgsFeature()
fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10,10)))
fet.setAttributes(["Johny", 2, 0.3])
pr.addFeatures([fet])

# commit to stop editing the layer
vl.commitChanges()

# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.updateExtents()

# add layer to the legend
QgsMapLayerRegistry.instance().addMapLayer(vl)
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.