用于设置图层的QCombo框(Python QGIS插件)
我正在尝试创建一个函数,用来根据在QComboBox中选择的项目来声明一个变量。这是为QGIS 2.0和2.2开发的一个插件。我遇到了一个“列表索引超出范围”的错误,但我不知道为什么会这样。我在想,可能是我的combobox.currentIndex()没有返回我想要的值。如果真是这样,我想我应该在程序运行之前,先给下拉框的索引设置一个默认值。
#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
现在我根据下面的接近答案对代码做了一些修改。layerChanged()现在使用了一种标识符的方法,而run()根据线程中的想法以不同的方式将图层添加到下拉框中,链接在这里:http://lists.osgeo.org/pipermail/qgis-developer/2010-November/011505.html。不过这两个地方仍然有问题。前者出现了“None类型对象没有mapLayer属性”的错误,后者则是“语法错误”。
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()
2 个回答
感谢@ekhumoro的帮助,现在这个问题解决了。对答案中的建议唯一的修改是在layerChanged()这个函数里:
def layerChanged(self):
registry = QgsMapLayerRegistry.instance()
identifier = str(self.dlg.ui.indivCombo.itemData(self.dlg.ui.indivCombo.currentIndex()))
self.indivLayer = registry.mapLayer(identifier)
这样做解决了我多个组合框中选择的索引混乱和不正确的问题。
根据你提供的示例代码,我发现了几个问题。
首先,从initGui
和run
这两个方法的不同来看,可能在使用两组下拉框。信号连接的是self.dlg.ui.*Combo
,而添加项目的是self.dlg.*Combo
。
其次,你似乎在不断地给下拉框添加内容,但没有先清空它们。
第三,你没有保持下拉框的索引和列表之间的一一对应关系,因为你是根据类型来过滤图层的。
最后,图层列表是来自一个map的值,所以它们的顺序并不能保证是一样的。
我建议你给每个下拉框项关联一个图层ID,然后通过mapLayer方法来获取图层。也就是说,像这样添加下拉框项:
self.dlg.indivCombo.addItem(layer.name(), layer.id())
然后像这样获取图层:
def layerChanged(self, index):
registry = QgsMapLayerRegistry.instance()
identifier = self.dlg.ui.indivCombo.itemData(index)
self.indivLayer = registry.mapLayer(identifier)
注意:如果你使用的是Python2,下拉框的数据会存储为QVariant
,所以你需要像这样提取标识符:
identifier = self.dlg.ui.indivCombo.itemData(index).toString()
或者这样:
identifier = self.dlg.ui.indivCombo.itemData(index).toPyObject()