- Release plans recap for the road to QGIS 1.0
- New version of eVis
- Contour Lines in Qgis
- QGIS and Google Summer of Code
- Quantum GIS Graduates OSGeo Incubation
- Paolo Cavallini Named to QGIS Project Steering Committee
- Nominations for QGIS PSC Open
- Capturing map coordinates in a stand alone app...
- Tutorial 7 - Creating spatial datasets with the QGIS API
- Html Image Plugin 0.2
Tutorial 6 - Working with vector attribute tables
In my last tutorial I showed you how to create temporary objects on the map canvas. Today I will giving you a basic introduction to using QgsFeatureAttribute - which allows your to retrieve the attributes for a feature in a vector layer. The attributes are descriptive data related to the geometry of the feature.
Note this is a repeat post since the original copy of this article disappeared from the blog.
First lets take a look at what we will achieve in this tutorial.

I suggest looking at the other tutorials before going through this one, though its not essential.
As with my previous tutorials, the entire project can be checked out from the QGIS Subversion repository using the following command:
svn co https://svn.qgis.org/repos/qgis/trunk/code_examples/6_accessing_vector_attributes
In the working directory for the tutorial code you will find a number of files including c++ sources and a simple data file under data. There is also the .ui file for the main window.
Note: You will need to edit the .pro file in the above svn directory to match your system. Also at some points in the code there are hard coded paths - you should adjust these as appropriate.
QgsFeatureAttribute
You can browse the code for QgsFeatureAttribute and related classes using the QGIS source browser. Look in the 'core' and 'gui' subdirectories. The classes we are particularly interested in are QgsFeature, QgsFeatureAttribute and QgsProvider. Also for more implementation examples, take a look at
qgsattributetable.cpp. Now on with our demo application....
In mainwindow.h you will notice the includes needed to work with feature attributes:
#include <qgsfeature.h>
#include <qgsfeatureattribute.h>
There are two main parts to this tutorial, both implmented in addLayer(). The first part lists the field names for the layer and puts it into our QTextBrowser on the form. The second part prints the values in each field for each feature in our sample data layer. Lets start by looking at the code to print the field names.
//get the field list associated with the layer std::vectormyFields = mypLayer->fields(); //we will hold the list of attributes in this string QString myString; //print out the field names first for (unsigned int i = 0; i < myFields.size(); i++ ) { //a little logic so we can produce output like : // "foo","bar","etc" if (i==0) { // here is where we actually get the field value myString = "\"" + myFields[i].name().trimmed() + "\""; } else { myString += ",\"" + myFields[i].name().trimmed() + "\""; } } textBrowser->append("Field List: " + myString);
If this looks a little familiar, don't be surprised - I used a similar approach in my labelling tutorial. The procedure is straight forward - we ask the layer for its fields, which are returned as a vector. Then we loop through the vector adding the name() value of each field to our string. The trimmed() function just strips off any white space on a QString.
Next we want to loop through the features to print out their attributes:
//get the provider associated with the layer
//the provider handles data io and is a plugin in qgis.
QgsVectorDataProvider* mypProvider=mypLayer->getDataProvider();
//check the provider is valid
if(mypProvider)
{
//create a holder for retrieving features from the provider
QgsFeature *mypFeature;
//get the provider ready to iterate through it
mypProvider->reset();
//now iterate through each feature
while ((mypFeature = mypProvider->getNextFeature(true)))
{
//get the attributes of this feature
const std::vector < QgsFeatureAttribute >& myAttributes = mypFeature->attributeMap();
//now loop through the attributes
for (int i = 0; i < myAttributes.size(); i++)
{
//a little logic so we can produce output like :
// "foo","bar","etc"
if (i==0)
{
// here is where we actually get the field value
myString = "\"" + myAttributes[i].fieldValue().trimmed() + "\"";
}
else
{
myString += ",\"" + myAttributes[i].fieldValue().trimmed() + "\"";
}
}
textBrowser->append("Field Values: " + myString);
//clean up before moving on to the next feature
delete mypFeature;
}
}
I've added in lots of comments in the code, so it should be pretty easy to understand what is going on. The basic steps are to get the provider for the layer, then ask it for features using getNextFeature() until no more features are returned. You can think of the features like a forward only cursor. You cant randomly jump from one record to the next, only iterate through them sequentially. For each feature we retrieve the list of attributes belonging to that feature and add them to a string to be appended to our QTextBrowser. Once we are done with the feature, we delete it to clean up.
QgsFeature is a cool thing - it lets you know all about the data related to a feature. Whats especially nice in QGIS is that the vector providers are abstracted, so you can use exactly the same procedure to read data from any supported OGR datasource, PostGIS, GPX etc. As more vector providers are added in the future you will automatically gain the ability to read attributes from their features thanks to the standard provider interface. Thats the end of tutorial6!
Mac Specific Notes
After building the application bundle (qmake; make) you can copy the spatial reference system database into the bundle to avoid 'cant find resource' type errors:
mkdir -p qgis_example6.app/Contents/MacOS/share/qgis/resources/
cp -r /Applications/qgis.app/Contents/MacOS/share/qgis/resources/* \
qgis_example6.app/Contents/MacOS/share/qgis/resources/
- Tim Sutton's blog
- Add new comment
- 3858 reads

Getting Tutorial 6 working with QGIS 0.9.1
Hi Tim,
Im new to QGIS programming and open source in general, and i would like to say thanks for the great tutorials!
I am currently using version 0.9.1 and have noticed that qgsfeatureattribute.h has been removed in this release.
is replacing this with QgsAttributeMap the recommended way to implement the attributes for this tutorial?
If so after implementing the following function: "const QgsAttributeMap& myAttributes = mypFeature.attributeMap();"
I dont seem to be pulling in the attributes into my map container. Do you know what im doing wrong here?
Also do you have a link to the 0.9.1 QGIS api that you use.
thanks.
Jenifer
Hi Tim, Jenifer. I am in a
Hi Tim, Jenifer.
I am in a similar situation with 0.9.1 and tutorial 6. I have tried both "const QgsAttributeMap& myAttributes = mypFeature.attributeMap()" and "QgsAttributeMap myAttributes = mypFeature.attributeMap()" and have no luck getting any attributes.
I have been playing with the code and have noticed that the feature retrieved using
"myProvider->getNextFeature(mypFeature)" provides a Feature that returns FALSE when i check "mypFeature.isValid()". Im not sure what isValid actually represents because the doumentation is a 'little' light on its implementation, but Im wondering if this implies that there is no attributes to pull out of the invalid Feature?
Any help on this would be great, thanks in advance,
Michael
a solution
Im not sure if this is due to the shift from 0.8.1 to 0.9.1 but it appears that before you can use the "myProvider->getNextFeature(myFeature)" function, you need to populate a list of features with a "select()" call.
I inserted the following code before the call to "getNextFeature()" and it got the code working. Maybe Tim can clarify if this is the actual cause of the problem or an oblique work around? ;)
// added code
QgsAttributeList fetchAttributes;
for(int i = 0; i < mypProvider->fieldCount(); i++)
{
fetchAttributes.append(i); // indicate each field is required
}
// select the list of features based on the selection criteria
mypProvider->select(fetchAttributes,QgsRect(),true,false);
//now iterate through each feature
while (mypProvider->getNextFeature(mypFeature))
{
:
:
Good luck Jenifer, hope this helps.
Regards
Michael Ostrognay
subsetString
Hi,
Can I obtain a record's subset of attribute table?
I'm try with subSetString method of MapLayer but don't work.
Please reply to me with an example.
Christian
Re: subsetString
Hi Christian
Without looking at the code, if I recall correctly only postgresql provider supports sql subsetting at this time.
Regards
Tim