I'm attempting to create a function to declare a variable in terms of an item chosen in a QComboBox. It's for a plugin for QGIS 2.0 and 2.2. I'm getting a "list index out of range" error, but cannot see why. I'm wondering if my combobox.currentIndex() isn't giving me what I think it is. If this is the case, I wonder if I should find a way set the combo box's index to something by default before the program runs.
#connecting the combo boxes to function
def initGui(self):
QObject.connect(self.dlg.ui.indivCombo,SIGNAL("currentIndexChanged(int)"),self.layerChanged)
QObject.connect(self.dlg.ui.grosCombo,SIGNAL("currentIndexChanged(int)"),self.layerChanged)
QObject.connect(self.dlg.ui.resCombo,SIGNAL("currentIndexChanged(int)"),self.layerChanged)
#function to set my layer parameter to the equal the item at index chosen
def layerChanged(self):
self.layerMap = QgsMapLayerRegistry.instance().mapLayers().values()
self.indivLayer = self.layerMap[self.dlg.ui.indivCombo.currentIndex()]
self.grosLayer = self.layerMap[self.dlg.ui.grosCombo.currentIndex()]
self.resLayer = self.layerMap[self.dlg.ui.resCombo.currentIndex()]
#populating combo box with layers in stack
def run(self):
# show the dialog
self.dlg.show()
for layer in self.iface.legendInterface().layers():
if layer.type() == QgsMapLayer.VectorLayer:
self.dlg.indivCombo.addItem(layer.name())
self.dlg.grosCombo.addItem(layer.name())
self.dlg.resCombo.addItem(layer.name())
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result == 1:
pass
I've now made some changes to the code thanks to the near-answer below. layerChanged() now uses an identifiers method and run() adds layers to combo box differently based on ideas from thread http://lists.osgeo.org/pipermail/qgis-developer/2010-November/011505.html . Both areas still give me issues however. "None type object has no attribute mapLayer" for the former and "Syntax error" for the latter.
def layerChanged(self, index):
#globals previously initialized as None
global registry, indivID, grosID, resID
registry = QgsMapLayerRegistry.instance()
indivID = self.dlg.ui.indivCombo.data(index).toPyObject()
grosID = self.dlg.ui.grosCombo.data(index).toPyObject()
resID = self.dlg.ui.resCombo.data(index).toPyObject()
self.indivLayer = registry.mapLayer(indivID)
self.grosLayer = registry.mapLayer(grosID)
self.resLayer = registry.mapLayer(resID)
def calculatelength(self):
global registry, resID
self.resLayer = registry.mapLayer(resID)
idx = self.resLayer.fieldNameIndex('Length')
#code continues
def run(self):
# show the dialog
self.dlg.show()
for layer in self.iface.legendInterface().layers():
if layer.type() == QgsMapLayer.VectorLayer:
self.dlg.ui.indivCombo.addItem(layer.name(),QVariant(layer.id())
self.dlg.ui.grosCombo.addItem(layer.name(),QVariant(layer.id())
self.dlg.ui.resCombo.addItem(layer.name(),QVariant(layer.id())
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result == 1:
pass
#AEPStats()
Taking example code you posted at face-value, I can see several problems.
Firstly, judging by the differences between the initGui
and run
methods, there may be two sets of combo-boxes in use. The signals are connected to self.dlg.ui.*Combo
, whereas the items are added to self.dlg.*Combo
.
Secondly, you seem to be populating the combo-boxes over and over again without clearing them beforehand.
Thirdly, you do not seem to be preserving a one-to-one relationship between the combo-box indexes and the list, because you are filtering the layers based on type.
And finally, the list of layers comes from the values of a map , so surely there is no guarantee that they will come out in the same order.
I would suggest you associate a layer id with each combo item, and then retrieve the layer via the mapLayer method. That is, add the combo items like this:
self.dlg.indivCombo.addItem(layer.name(), layer.id())
and then retrieve the layer like this:
def layerChanged(self, index):
registry = QgsMapLayerRegistry.instance()
identifier = self.dlg.ui.indivCombo.itemData(index)
self.indivLayer = registry.mapLayer(identifier)
NB: if you're using Python2, the combo data will be stored as a QVariant
so you would need to extract the identifier like this:
identifier = self.dlg.ui.indivCombo.itemData(index).toString()
or this:
identifier = self.dlg.ui.indivCombo.itemData(index).toPyObject()
Thanks to help from @ekhumoro, this now works. Only changes made to answer's suggestions were in layerChanged():
def layerChanged(self):
registry = QgsMapLayerRegistry.instance()
identifier = str(self.dlg.ui.indivCombo.itemData(self.dlg.ui.indivCombo.currentIndex()))
self.indivLayer = registry.mapLayer(identifier)
This solves an issue of the index chosen getting mixed up and incorrect for the multiple combo boxes i have.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.