Có thể thay đổi các biểu tượng huyền thoại trong huyền thoại nhà soạn nhạc in QGIS?


9

Tôi có một số lớp với các ký hiệu được xác định dữ liệu rất phức tạp. Nếu tôi sử dụng một chú giải trong trình soạn thảo in, các ký hiệu này không được vẽ chính xác.

Có cách nào để thay đổi biểu tượng chú giải bằng pyqgis, vì vậy tôi có thể sử dụng hình ảnh PNG hoặc SVG tùy chỉnh thay vì biểu tượng chú giải mặc định cho các lớp này không?

Tôi biết cách thêm Nút ấn vào trình soạn thảo In và cách kết nối nó với một chức năng. Tôi muốn thêm một nút vào Cài đặt chú thích để cho phép tôi thay thế biểu tượng chú giải được tạo tự động bằng hình ảnh tùy chỉnh. Vì vậy, những gì tôi vẫn cần là thông tin về cách tôi có thể truy cập các biểu tượng huyền thoại bằng pyqgis / pyqt, và làm thế nào để thay thế chúng bằng QImage trên QLabel hoặc một cái gì đó tương tự?

Mockup rất cơ bản của nút được sử dụng để thay đổi biểu tượng:

nhập mô tả hình ảnh ở đây

Truyền thuyết được tạo tự động:

nhập mô tả hình ảnh ở đây

Truyền thuyết với biểu tượng truyền thuyết tùy chỉnh:

nhập mô tả hình ảnh ở đây

Tôi đã tìm ra cách truy cập các mục của chú giải trong trình soạn thảo in nhưng chưa biết cách truy cập vào biểu tượng:

import qgis
from PyQt4.QtCore import *
from PyQt4.QtGui import *

activeComposer = iface.activeComposers()

for item in activeComposer:
    if item.composerWindow().windowTitle()=='test':
        for i in item.items():
            if isinstance(i,QgsComposerLegend):
                #print i
                #print i.model()
                legend = i
                for i in xrange(legend.modelV2().rowCount()):
                    posteleg=legend.modelV2().index(i, 0)
                    print posteleg.data()

Chỉnh sửa 1:

Tôi cũng đã tìm ra cách truy cập QIcon-Object của cây huyền thoại nhưng chưa thể trao đổi chúng:

def run(self):

        activeComposer = self.iface.activeComposers()
        #print(self.resolve('icon.png'))
        for item in activeComposer:
            if item.composerWindow().windowTitle()=='test':
                for i in item.items():
                    if isinstance(i,QgsComposerLegend):
                        legend = i

                        layerIcon = QIcon(os.path.join(os.path.dirname(__file__), "icon.png"))

                        for i in xrange(legend.modelV2().rowCount()):
                            posteleg=legend.modelV2().index(i, 0)
                            posteleg.model().iconGroup().swap(layerIcon)
                            print posteleg.data()

Đây là một ví dụ thực tế trong đó bạn có thể thấy một biểu tượng kết hợp của nhiều lớp biểu tượng: nhập mô tả hình ảnh ở đây Điều này sẽ kết thúc trong truyền thuyết như thế này: nhập mô tả hình ảnh ở đây

Khi tôi cần biểu tượng thích hợp trong truyền thuyết, tôi muốn tạo một ảnh chụp màn hình biểu tượng của mình, cắt nó và sử dụng nó như một hình ảnh trong truyền thuyết của tôi.

Tôi biết tôi chỉ có thể phủ một hình ảnh riêng biệt lên trên chú giải của mình bao gồm biểu tượng được tạo tự động nhưng tôi muốn có một giải pháp "sạch hơn" cho phép tôi thay thế các biểu tượng trong truyền thuyết bằng hình ảnh tùy chỉnh.

Chỉnh sửa 2:

Trong khi đó, tôi đã tìm thấy một cách khác để có quyền truy cập vào các mục huyền thoại:

from qgis.core import QgsLegendRenderer, QgsComposerLegendStyle

compDict = {}
for comp in iface.activeComposers():
    # workaround to get name: read it from window title
    compDict[comp.composerWindow().windowTitle()] = comp.composition()
if "mycomposername" in compDict:
    itemLlegend = compDict["mycomposername"].getComposerItemById("mylegend_id")
    if itemLlegend:
        print itemLlegend

tree_layer_layer =  itemLlegend.modelV2().rootGroup().children()
for item in tree_layer_layer:
        if item.layerName()=="MyLayername":
            print "match"
            QgsLegendRenderer.setNodeLegendStyle(item, QgsComposerLegendStyle.Group)

Điều này cho phép tôi truy cập các đối tượng QssLayerTreeLayer và tôi có thể chuyển đổi Phong cách huyền thoại (Nhóm, Nhóm phụ, Ẩn). Nhưng tôi vẫn không biết làm thế nào để truy cập vào biểu tượng huyền thoại. Có ý kiến ​​gì không?


1
Khi tôi gặp vấn đề này với QGIS, tôi thường sẽ tạo các lớp bổ sung có ký hiệu tôi muốn hiển thị trong chú giải (thường là các bản sao đơn giản của các lớp hiện có - không phải là nguồn dữ liệu mới). Sau đó, trong trình soạn thảo, tôi thiết lập cửa sổ bản đồ và khóa các lớp. Sau khi các lớp bị khóa, tôi bật các lớp "giả" và có thể thêm chúng vào một huyền thoại. Đây hoàn toàn là một cách giải quyết, và không phải trong PyQGIS, nhưng có lẽ có một số cách để mô phỏng các lớp "giả" cho những gì bạn cần?
Nate Wanner

Câu trả lời:


10

Vì chủ đề này bao gồm rất nhiều tranh luận, tôi sẽ chỉ tập trung vào các lớp biểu tượng SVG, hy vọng rằng tôi đã hiểu rõ những gì bạn đang tìm kiếm (Tôi không nhận ra độ dài của câu trả lời trong khi viết, vì vậy tôi xin lỗi vì điều đó nhưng tôi hy vọng nó sẽ thêm rõ ràng hơn, mặc dù).


Bối cảnh

1) Các lớp biểu tượng

Các lớp lớp biểu tượng sau đây có sẵn cho định dạng SVG:

  • QssSvgMarkerSymbolLayerV2 , hiển thị hình dạng điểm bằng hình ảnh SVG được chỉ định (nó hoạt động cho các lớp điểm );
  • QssSVGFillSymbolLayer , vẽ bên trong hình học đa giác bằng hình ảnh SVG lặp lại (nó hoạt động cho các lớp đa giác ).

Một cách tiếp cận phổ biến để tạo một lớp biểu tượng là khởi tạo nó với một từ điển các thuộc tính.

Bạn có thể khởi tạo một lớp biểu tượng mới và xem các thuộc tính mặc định của nó theo cách này:

symbol_layer = QgsSvgMarkerSymbolLayerV2()
for k,v in symbol_layer.properties().iteritems():
    print k, ':', v

Bạn sẽ có được tất cả các thuộc tính được lưu trữ trong đó:

outline_width : 0.2
outline_color : 0,0,0,255
angle : 0
name : crosses/Star1.svg
scale_method : diameter
color : 0,0,0,255
size_unit : MM
horizontal_anchor_point : 1
size_map_unit_scale : 0,0,0,0,0,0
outline_width_unit : MM
offset : 0,0
offset_map_unit_scale : 0,0,0,0,0,0
outline_width_map_unit_scale : 0,0,0,0,0,0
size : 4
vertical_anchor_point : 1
offset_unit : MM

Nếu bạn muốn chỉnh sửa các thuộc tính, bạn có thể sử dụng các phương thức có thể gọi được từ sự trợ giúp của lớp (ví dụ: chạy help(QgsSvgMarkerSymbolLayerV2)trong Bảng điều khiển Python). Sau này bạn sẽ thấy một ví dụ về cách sử dụng các phương thức.

Để hoàn thiện, bạn cũng có thể khởi tạo một lớp biểu tượng với một từ điển các thuộc tính (ví dụ, xem ở đây ), nhưng tôi thực sự thích cách tiếp cận đầu tiên và tôi sẽ sử dụng nó.

2) Tạo trình kết xuất

Để sử dụng lớp biểu tượng một khi bạn đã tạo nó (và cuối cùng được chỉnh sửa), bạn cần tạo một trình kết xuất phù hợp và sau đó gán trình kết xuất đó cho lớp bản đồ của bạn.

Để truy cập trình kết xuất hiện có của một lớp:

renderer = layer.rendererV2()

Để có danh sách các loại trình kết xuất có sẵn, hãy sử dụng:

renderer_types = QgsRendererV2Registry().renderersList()

Đối với trường hợp của bạn, chúng ta nên xử lý trình kết xuất biểu tượng Phân loại . Như tôi đã nói trước đây, bạn cần tạo một trình kết xuất và sau đó gán nó cho lớp:

# define the lookup: value -> (color, label)
landuses = {'Agriculture': ('#d3a151', 'Agriculture'), 'Natural': ('#175dcd', 'Natural'),}

# create a category for each item in landuses
categories = []
for landuse_name, (color, label) in landuses.items():
    symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
    symbol.setColor(QColor(color))
    category = QgsRendererCategoryV2(landuse_name, symbol, label)
    categories.append(category)

# create the renderer and assign it to the layer
expression = 'landuse' # field name
renderer = QgsCategorizedSymbolRendererV2(expression, categories) # categorized symbol renderer
layer.setRendererV2(renderer) # assign the renderer to the layer

3) Thay đổi lớp biểu tượng

Một số biểu tượng của trình kết xuất biểu tượng Phân loại có thể gọi được symbols()(nó trả về một danh sách):

for symb in renderer.symbols():
    print symb

<qgis._core.QgsMarkerSymbolV2 object at 0x0E1FF760>
<qgis._core.QgsMarkerSymbolV2 object at 0x0E1FF7B0>

Nếu bạn muốn thay thế một lớp biểu tượng nhất định trong phạm vi symbolđược xác định trước đó, bạn chỉ cần biết chỉ mục của nó và sau đó nói với trình kết xuất theo cách này:

renderer.symbols()[0].changeSymbolLayer(0, new_symbol)

trong đó [0]chỉ ra mục đầu tiên của nhóm được phân loại.

Giải pháp

Cuối cùng, hãy áp dụng những gì chúng ta vừa học!

Giả sử hoạt động trên lớp đa giác này, nơi lưu trữ việc sử dụng đất mà chúng ta đã xác định trước đây:

nhập mô tả hình ảnh ở đây

Nếu bạn muốn thay đổi mẫu mặc định cho việc sử dụng đất nông nghiệp (họ có vị trí số 1 trong nhóm 'sử dụng đất') với hình ảnh SVG cụ thể, bạn có thể chạy mã này (đọc tại đây để biết cách thêm SVG tùy chỉnh con đường):

import qgis
from PyQt4.QtCore import *
from PyQt4.QtGui import *

# define the lookup: value : (color, label)
landuses = {'Agriculture': ('#d3a151', 'Agriculture'), 'Natural': ('#175dcd', 'Natural'),}

# create a category for each item in landuses
categories = []
for landuse_name, (color, label) in landuses.items():
    symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
    symbol.setColor(QColor(color))
    category = QgsRendererCategoryV2(landuse_name, symbol, label)
    categories.append(category)

# create the renderer and assign it to the layer
expression = 'landuse' # field name
renderer = QgsCategorizedSymbolRendererV2(expression, categories)

activeComposer = iface.activeComposers()
for item in activeComposer:
    if item.composerWindow().windowTitle()=='test':
        for i in item.items():
            if isinstance(i,QgsComposerLegend):
                legend = i
                for k in xrange(legend.modelV2().rowCount()):
                    posteleg=legend.modelV2().index(k, 0)
                    layer = QgsMapLayerRegistry.instance().mapLayersByName( posteleg.data() )[0]
                    if k == 0: # k is the position of the layer of interest in Legend (NOT in the Layers Panel)
                        svg_location = 'C:/path_to_svg/smile.svg'
                        new_symbol = QgsSVGFillSymbolLayer()
                        new_symbol.setSvgFilePath(svg_location)
                        new_symbol.setPatternWidth(7.0)
                        #... If you want to set additional parameters, type help(QgsSVGFillSymbolLayer) in the Python Console
                        renderer.symbols()[1].changeSymbolLayer(0, new_symbol)
                    layer.setRendererV2(renderer)
                    layer.triggerRepaint()

Đây sẽ là kết quả:

nhập mô tả hình ảnh ở đây

Đoạn mã trên rất thô sơ, nhưng vì tôi không biết bạn muốn một giải pháp cụ thể cho ví dụ của bạn hay giải thích chung chung hơn, tôi thích tập trung sự chú ý vào các công cụ có sẵn thay vì tự tinh chỉnh mã (Tôi chắc chắn bạn có thể chỉnh sửa nó một chút theo nhu cầu cụ thể của bạn!).


Cảm ơn câu trả lời sâu rộng của bạn nhưng tôi đang tìm kiếm một giải pháp để thay đổi biểu tượng (chỉ) trong huyền thoại nhà soạn nhạc không phải cho chính lớp đó. Tôi sẽ cập nhật câu hỏi của tôi ở trên trong một giây với một ví dụ nữa
markgraeflerland

@markgraeflerland Tôi chắc chắn không ai nghĩ về vấn đề được giải thích trong câu hỏi được chỉnh sửa (thực tế mới) của bạn. Bạn không bao giờ chỉ định rằng hình ảnh trong truyền thuyết sẽ không tái tạo những gì bạn nhìn thấy trong lớp (có vẻ như bạn muốn thay thế một mục từ truyền thuyết bằng một hình ảnh, như tôi đã làm). Trân trọng, theo tôi, câu hỏi ban đầu của bạn rất sai lệch và bài viết của tôi thực sự đã cố gắng đưa ra câu trả lời cho nó. Tôi xin lỗi vì đã lãng phí thời gian, nhưng tôi sẽ không xóa câu trả lời vì nó có thể khiến người khác quan tâm khi googling. Chúc may mắn với nghiên cứu của bạn!
mgri

2
Trong câu đầu tiên của câu hỏi tôi đã viết "Nếu tôi sử dụng một chú giải trong nhà soạn nhạc in thì những biểu tượng này không được vẽ chính xác" vì vậy tôi không nghĩ rằng tôi đã không chỉ định rằng hình ảnh trong truyền thuyết sẽ không tái tạo những gì tôi xem trong lớp
markgraeflerland

5

Ngoài ra, và không có mã hóa Python, tôi đã giải quyết điều này bằng cách tạo một nhóm lớp mới dành riêng cho việc tạo huyền thoại, nơi tôi có thể đặt bất cứ thứ gì tôi thích, với kích thước và màu sắc tôi muốn. Như thế này trong trình soạn thảo in, tôi vừa xóa khỏi các mục chú thích các lớp dữ liệu thực tế và chỉ giữ lại nhóm lớp chú giải.

Nó đặc biệt thiết thực khi cần tạo một huyền thoại có thể đại diện cho các trường hợp không xảy ra trong bản đồ in thực tế.

EDIT: và về lần chỉnh sửa thứ hai của bạn, với các biểu tượng tổng hợp không hiển thị đúng, bạn có một số biến xác định các ký hiệu của mình, như "C" ou "G" trên thực tế có liên quan đến một trường hoặc hướng không? Nếu đó là trường hợp, QGIS không thể đoán những gì bạn muốn được hiển thị, vì vậy nó đi bằng cách hiển thị mọi thứ mà không có bất kỳ giá trị nào cho các tham số này. Một cách giải quyết có thể là để biểu thị lưu ký hiệu với một số giá trị cố định thay cho các biến. Cách này cho phép tôi thay thế mục chú thích hiển thị mặc định này: nhập mô tả hình ảnh ở đâybằng cách này phù hợp với nhu cầu của tôinhập mô tả hình ảnh ở đây

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.