0

I want to display data based on the feature currently selected/clicked on.

I am following a tutorial from http://www.qgisworkshop.org/html/workshop/plugins_tutorial.html.

It initially shows you how to use the Textbrowser to display the coordinates currently clicked on and developing that functionality further, it allows you to see the information regarding a respective feature.

I have the following function which as per example in the above mentioned tutorial is set to retrieve the respective data. In the example it refers to the field name "NAME" which from what I can understand refers to the name of the field in the attribute table for the respective layer in question.

My attribute table structure is as follows:

field names:

objectid
str_add_id
building_number
building_name_id
street_name_id
etc etc

The field I wish to retrieve is that of the "str_add_id" therefore using his example in the tutorial:

His Example:

def updateTextBrowser(self):
 # if we have a selected feature
 if self.selectList:
 # find the index of the 'NAME' column, branch if has one or not
 nIndx = self.provider.fieldNameIndex('NAME')
 # get our selected feature from the provider, but we have to pass in an empty feature and the column index we want
 sFeat = QgsFeature()
 if self.provider.featureAtId(self.selectList[0], sFeat, True, [nIndx]):
 # only if we have a 'NAME' column
 if nIndx != -1:
 # get the feature attributeMap
 attMap = sFeat.attributeMap()
 # clear old TextBrowser values
 self.dlg.clearTextBrowser()
 # now update the TextBrowser with attributeMap[nameColumnIndex]
 # when we first retrieve the value of 'NAME' it comes as a QString so we have to cast it to a Python string
 self.dlg.setTextBrowser( str( attMap[nIndx].toString() ))

In my example, I basically replaced the nIndx = self.provider.fieldNameIndex('NAME') changing the "'NAME'" to "'str_add_id'".

Unfortunately however upon clicking on the feature I do not get the requested data. I still receive the X and Y coordinates of the point clicked on in the layer.

Any ideas as to what I could be doing wrong? I have attached my whole plugin code below:

# -*- coding: utf-8 -*-
"""
/***************************************************************************
 testplug
 A QGIS plugin
 Test plugin through builder
 -------------------
 begin : 2013年05月08日
 copyright : (C) 2013 by Test
 email : [email protected]
 ***************************************************************************/
/***************************************************************************
 * *
 * This program is free software; you can redistribute it and/or modify *
 * it under the terms of the GNU General Public License as published by *
 * the Free Software Foundation; either version 2 of the License, or *
 * (at your option) any later version. *
 * *
 ***************************************************************************/
"""
# Import the PyQt and QGIS libraries
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
# Initialize Qt resources from file resources.py
import resources
# Import the code for the dialog
from testplugdialog import testplugDialog
class testplug:
 def __init__(self, iface):
 # Save reference to the QGIS interface
 self.iface = iface
 #A reference to our map canvas
 self.canvas = self.iface.mapCanvas()
 #Change
 # this QGIS tool emits as QgsPoint after each click on the map canvas
 self.clickTool = QgsMapToolEmitPoint(self.canvas)
 # create our GUI dialog
 self.dlg = testplugDialog()
 # create a list to hold our selected feature ids
 self.selectList = []
 # current layer ref (set in handleLayerChange)
 self.cLayer = None
 # current layer dataProvider ref (set in handleLayerChange)
 self.provider = None
 # initialize plugin directory
 self.plugin_dir = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/python/plugins/testplug"
 # initialize locale
 localePath = ""
 locale = QSettings().value("locale/userLocale").toString()[0:2]
 if QFileInfo(self.plugin_dir).exists():
 localePath = self.plugin_dir + "/i18n/testplug_" + locale + ".qm"
 if QFileInfo(localePath).exists():
 self.translator = QTranslator()
 self.translator.load(localePath)
 if qVersion() > '4.3.3':
 QCoreApplication.installTranslator(self.translator)
 # Create the dialog (after translation) and keep reference
 self.dlg = testplugDialog()
 def initGui(self):
 # Create action that will start plugin configuration
 self.action = QAction(
 QIcon(":/plugins/testplug/icon.png"),
 u"Test Plugin through builder", self.iface.mainWindow())
 # connect the action to the run method
 QObject.connect(self.action, SIGNAL("triggered()"), self.run)
 # Add toolbar button and menu item
 self.iface.addToolBarIcon(self.action)
 self.iface.addPluginToMenu(u"&testplug", self.action)
 # connect our custom function to a clickTool signal that the canvas was clicked
 #result = QObject.connect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.handleMouseDown)
 #QMessageBox.information( self.iface.mainWindow(),"Info", "connect = %s"%str(result) )
 # connect our select function to the canvasClicked signal
 #result = QObject.connect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.selectFeature)
 #QMessageBox.information( self.iface.mainWindow(),"Info", "connect = %s"%str(result) )
 QObject.connect(self.dlg.ui.chkActivate,SIGNAL("stateChanged(int)"),self.changeActive)
 # connect to the currentLayerChanged signal of QgsInterface
 result = QObject.connect(self.iface, SIGNAL("currentLayerChanged(QgsMapLayer *)"), self.handleLayerChange)
 # QMessageBox.information( self.iface.mainWindow(),"Info", "connect = %s"%str(result) )
 def handleLayerChange(self, layer):
 self.cLayer = self.canvas.currentLayer()
 if self.cLayer:
 self.provider = self.cLayer.dataProvider()
 def changeActive(self,state):
 if (state==Qt.Checked):
 # connect to click signal
 QObject.connect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.handleMouseDown)
 # connect our select function to the canvasClicked signal
 QObject.connect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.selectFeature)
 else:
 # disconnect from click signal
 QObject.disconnect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.handleMouseDown)
 # disconnect our select function to the canvasClicked signal
 QObject.disconnect(self.clickTool, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.selectFeature)
 def unload(self):
 # Remove the plugin menu item and icon
 self.iface.removePluginMenu(u"&testplug", self.action)
 self.iface.removeToolBarIcon(self.action)
 def handleMouseDown(self, point, button):
 self.dlg.clearTextBrowser()
 self.dlg.setTextBrowser( str(point.x()) + " , " +str(point.y()) )
 #QMessageBox.information( self.iface.mainWindow(),"Info", "X,Y = %s,%s" % (str(point.x()),str(point.y())) )
 def selectFeature(self, point, button):
 # QMessageBox.information( self.iface.mainWindow(),"Info", "in selectFeature function" )
 # setup the provider select to filter results based on a rectangle
 pntGeom = QgsGeometry.fromPoint(point)
 # scale-dependent buffer of 2 pixels-worth of map units
 pntBuff = pntGeom.buffer( (self.canvas.mapUnitsPerPixel() * 2),0)
 rect = pntBuff.boundingBox()
 # get currentLayer and dataProvider
 self.cLayer = self.canvas.currentLayer()
 self.selectList = []
 if self.cLayer:
 self.provider = self.cLayer.dataProvider()
 feat = QgsFeature()
 # create the select statement
 self.provider.select([],rect) # the arguments mean no attributes returned, and do a bbox filter with our buffered rectangle to limit the amount of features
 while self.provider.nextFeature(feat):
 # if the feat geom returned from the selection intersects our point then put it in a list
 if feat.geometry().intersects(pntGeom):
 self.selectList.append(feat.id())
 if self.selectList:
 # make the actual selection
 self.cLayer.setSelectedFeatures(self.selectList)
 # update the TextBrowser
 self.updateTextBrowser()
 else:
 QMessageBox.information( self.iface.mainWindow(),"Info", "No layer currently selected in TOC" )
 def updateTextBrowser(self):
 # if we have a selected feature
 if self.selectList:
 # find the index of the 'NAME' column, branch if has one or not
 nIndx = self.provider.fieldNameIndex('objectid')
 # get our selected feature from the provider, but we have to pass in an empty feature and the column index we want
 sFeat = QgsFeature()
 if self.provider.featureAtId(self.selectList[0], sFeat, True, [nIndx]):
 # only if we have a 'NAME' column
 if nIndx != -1:
 # get the feature attributeMap
 attMap = sFeat.attributeMap()
 # clear old TextBrowser values
 self.dlg.clearTextBrowser()
 # now update the TextBrowser with attributeMap[nameColumnIndex]
 # when we first retrieve the value of 'NAME' it comes as a QString so we have to cast it to a Python string
 self.dlg.setTextBrowser( str( attMap[nIndx].toString() ))
 # run method that performs all the real work
 def run(self):
 # set the current layer immediately if it exists, otherwise it will be set on user selection
 self.cLayer = self.iface.mapCanvas().currentLayer()
 if self.cLayer: self.provider = self.cLayer.dataProvider()
 # make our clickTool the tool that we'll use for now
 self.canvas.setMapTool(self.clickTool)
 # show the dialog
 self.dlg.show()
 # Run the dialog event loop
 result = self.dlg.exec_()
 # See if OK was pressed
 if result == 1:
 # do something useful (delete the line containing pass and
 # substitute with your code)
 pass

Thanks in advance!

dmci
4,9322 gold badges23 silver badges33 bronze badges
asked May 20, 2013 at 10:23

2 Answers 2

1

You still have handleMouseDown connected to canvasClicked. Both methods ( handleMouseDown and selectFeature ) will be called and as they both clear and write the box, the first one will be overwritten by the second one. Just remove one of the two connects and you should be fine.

As a side-note, if your project gets bigger you would probably want to separate this logic from the main plugin code. QgsMapTool facilitates stuff like this. See also How to programatically check for a mouse click in QGIS

answered Aug 2, 2013 at 12:26
0

The line

nIndx = self.provider.fieldNameIndex('objectid')

returns your object ID, not your "str_add_id" attribute index.

Maybe that typo will fix your problem.

answered Aug 2, 2013 at 10:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.