2

I'd like to ask on how can I categorize by attribute using my shapefile via python / custom plugin.

I have a Municipality and field name of "Land_Classification" with values "Residential, Commercial and Industrial". I would like to create a plugin that if i click it the layer will automatically categorize the shapefile by Land Classification and will be have colors by Residential, Commercial and Industrial.

PolyGeo
  • 65,136
  • 29
  • 109
  • 338

1 Answers1

3

Personally, I would avoid creating a function in your plugin which allows the user to click a layer and apply a certain style (unless you add some sort of checkbox to enable/disable this function).

What I would do is:

  1. Create a combo box and populate this with the names of the loaded layers
  2. Create a function which defines the parameters of the categorised style
  3. Create a push button which applies the above function to the selected layer in the combo box

So you could use something like the following in your main.py file. Add the imports at the top of the script:

from qgis.core import QgsMapLayerRegistry, QgsSymbolV2, QgsRendererCategoryV2, QgsCategorizedSymbolRendererV2
from PyQt4.QtGui import QColor

Then in the main run() function, you can use:

def run(self):
    # Define a list for layer names
    layer_list = []
    # Get all layer names loaded in QGIS and store them in the list   
    for layer in QgsMapLayerRegistry.instance().mapLayers().values():
        layerName = layer.name()
        layer_list.append(layerName)
    # Clear layer combo box to make sure if plugin is loaded again, the list is not duplicated
    self.dlg.comboBox_layer.clear()
    # Add layers from list to combobox
    self.dlg.comboBox_layer.addItems(layer_list)

    def apply_style():
        # Get currently selected layer in combo box
        current_layer = self.dlg.comboBox_layer.currentText()
        layer = QgsMapLayerRegistry.instance().mapLayersByName(str(current_layer))[0]

        # Define style parameters: value, colour, legend
        land_class = {
        'Residential': ('#f00', 'Residential'),
        'Commercial': ('#0f0', 'Commercial'),
        'Industrial': ('#fff', 'Industrial'),
        }

        # Define a list for categories
        categories = []
        # Define symbology depending on layer type, set the relevant style parameters
        for classes, (color, label) in land_class.items():
            symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
            symbol.setColor(QColor(color))
            category = QgsRendererCategoryV2(classes, symbol, label)
            categories.append(category)

        # Column/field name to be used to read values from
        column = 'Land_Class'
        # Apply the style rendering
        renderer = QgsCategorizedSymbolRendererV2(column, categories)
        layer.setRendererV2(renderer)
        # Refresh the layer
        layer.triggerRepaint()

    # Set up push button to connect to above function
    run_button = self.dlg.style_button
    run_button.clicked.connect(apply_style)
Joseph
  • 75,746
  • 7
  • 171
  • 282
  • 1
    Wow! Thanks sir Joseph. Sorry for my late reply I was out of town for projects. I will try what you suggested and will give you feedback. – Conrado Domingo Oct 13 '16 at 10:31
  • @ConradoDomingo - Most welcome! I implemented something very similar recently so thought to post it as it might be helpful =) – Joseph Oct 13 '16 at 10:35
  • In step 2 im getting a little confused.. how can I create a function thats not in a plugin? – Conrado Domingo Oct 13 '16 at 11:22
  • @ConradoDomingo - Apologies, probably not very clear. The function is in the code (def apply_style(): which you add to the plugin. – Joseph Oct 13 '16 at 11:25
  • yes I added it already. :) but apparently when i click style_button nothing happens.. I think im missing something.. – Conrado Domingo Oct 13 '16 at 11:29
  • Did you reload the plugin or restart QGIS? – Joseph Oct 13 '16 at 11:31
  • Yes sir. everytime I make changes I reload the plugin and restart qgis. – Conrado Domingo Oct 13 '16 at 11:39
  • Perhaps an indentation issue? The code for the style_button should be outside the def apply_style(): function but inside the run(self): function. A good way to test your plugin is to open the Python Console and this will mention if any errors occur. Also, you can add print statements after certain lines to see if they are being read. – Joseph Oct 13 '16 at 11:44
  • Hi sir Joseph. I will try it by tomorrow. because im currently working on time keeping project. :) I will let you know what happens. – Conrado Domingo Oct 13 '16 at 15:39
  • Hi sir Josep, I created a comboBox and named it comboBox_layer also I created a push button and named it style_button. I used the above code in the land_class parameters 'Residential' : ('#f00' , 'Residential') which part of Residential is for database to read? because in land_class field my residential is ALL CAPS. – Conrado Domingo Oct 14 '16 at 02:39
  • @ConradoDomingo - The first part is for values so in your case it would be: 'RESIDENTIAL': ('#f00', 'Residential'). The syntax is basically value: ('colour', 'legend'). – Joseph Oct 14 '16 at 09:34
  • ok.. trying it now sir @Joseph. :) – Conrado Domingo Oct 14 '16 at 09:52
  • Hi sir Joseph, I tried it again but sad to say when I click on style_button and press ok from dialog box nothing happens..

    let me confirm step 1. I create a comboBox and name it comboBox_layer then put text inside like Residential, Commercial and Industrial. What layers should I populate?

    – Conrado Domingo Oct 14 '16 at 10:06
  • Hmm, my idea was that the comboBox_layer should contain all layers loaded into QGIS. Can you confirm this is what happens? – Joseph Oct 14 '16 at 10:11
  • I created a comboBox and name it comboBox_layer.. Yes I back read and found out that self.dlg.comboBox_layer.addItems(layer_list) should add my layers Naguilian.shp and naguiliandb.csv am I correct? – Conrado Domingo Oct 14 '16 at 10:14
  • Yes, you are correct. I suggest you open the Python Console when you run your plugin and see what errors (if any) show up when you click the style_button. – Joseph Oct 14 '16 at 10:17
  • heres my python console result sir Joseph, – Conrado Domingo Oct 14 '16 at 10:24
  • https://i.imgsafe.org/0b25641f97.jpg – Conrado Domingo Oct 14 '16 at 10:24
  • I have created a simple dialog plugin for you, you can download it here, extract it to your /.qgis2/python/plugins/ directory, restart QGIS and enable the plugin through the Plugins > Manage and Install Plugins... menu. I did not realise I needed to add a few more imports but it seems to work fine. – Joseph Oct 14 '16 at 10:47
  • trying it now sir Joseph. :) – Conrado Domingo Oct 14 '16 at 10:47
  • sir Joseph why the plugin icon is not loading in qgis? – Conrado Domingo Oct 14 '16 at 10:58
  • Did you enable it from the menu: Plugins > Manage and Install Plugins...? The plugin is called "Example". – Joseph Oct 14 '16 at 10:59
  • its working now. :) really great help.. but could you explain to me the process? :) – Conrado Domingo Oct 14 '16 at 11:03
  • Phew! Glad it works =). Process on how to create the plugin or show how the code works? – Joseph Oct 14 '16 at 11:10
  • on how the code works so I can review it. :) – Conrado Domingo Oct 14 '16 at 11:15
  • @ConradoDomingo - Edited post to include comments within the code ;) – Joseph Oct 14 '16 at 11:59
  • A million thanks sir Joseph! :) Next time ill try with labels. :) – Conrado Domingo Oct 14 '16 at 12:01