用于设置图层的QCombo框(Python QGIS插件)

0 投票
2 回答
2977 浏览
提问于 2025-04-18 02:05

我正在尝试创建一个函数,用来根据在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 个回答

1

感谢@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)

这样做解决了我多个组合框中选择的索引混乱和不正确的问题。

1

根据你提供的示例代码,我发现了几个问题。

首先,从initGuirun这两个方法的不同来看,可能在使用两组下拉框。信号连接的是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()

撰写回答