动态可更改的QCheckBox列表

时间:2017-09-05 14:42:53

标签: python qt pyqt qgis

我目前正在使用Python 2.7和PyQt 4开发QGIS插件。我的插件应该有可检查的地图图层列表(可能是项目列表,不相关),每次用户打开“设置”选项卡时都会重新生成。虽然我设法创建了QCheckBoxes的可检查列表,每次单击“设置”按钮时它都会重新生成,但它仍然远不是好的和功能性的。正如我所知,我的问题主要是父子关系和布局删除。

    self.layers = qgis_api.get_layers()
    #ScrollArea setup
    if (api.selected_upload_layers == [] and
        api.project.layerTreeRoot().children() != []):
        self.tmp_layers = qgis_api.get_layers()
        self.layout = QVBoxLayout(self.settingsDock.groupBox)
        self.scroll = QScrollArea()
        self.layout.addWidget(self.scroll)
        self.scroll.setWidgetResizable(True)
        self.scroll.setFixedHeight(111)
        self.scrollContent = QWidget(self.scroll)
        self.scrollLayout = QVBoxLayout(self.scrollContent)
        self.scrollContent.setLayout(self.scrollLayout)
        self.scroll.setWidget(self.scrollContent)

    i = 0
    self.checkboxes = []
    for layer in self.layers:
        self.checkboxes.append(QCheckBox("{0}".format(layer.name())))
        self.checkboxes[i].stateChanged.connect(lambda checked, i = i : self.cBoxChecked(self.checkboxes[i])) #inverts logic if run every time
        # check logic
        if i < len(self.layers)-1:
            i += 1
    # Create checkboxes first time
    if not api.upload:  #api.upload becomes true when clicked save in settings
        for i in range(0, len(self.layers)):
            try:
                self.scrollLayout.addWidget(self.checkboxes[i])
                self.checkboxes[i].setChecked(True)
            except Exception as e:
                print str(e)
    # compare layer list at creation and now to notice difference
    elif self.tmp_layers != self.layers:
        for i in range(0, self.scrollLayout.count()):
            self.scrollLayout.removeItem(self.scrollLayout.itemAt(0))
            try:  # delete old layer items
                for i in range(0, len(self.layers)):
                    self.scrollLayout.addWidget(self.checkboxes[i])
                    self.checkboxes[i].setChecked(True)
            except Exception as e:
                print str(e)

函数cBoxChecked()如下:

    def cBoxChecked(self, cBox):
    """ Add functionality  to ScrollArea checkboxes."""
    if cBox.isChecked():
          if cBox.text() not in api.selected_upload_layers:
               api.selected_upload_layers.append(cBox.text())
    else:
          try:
               api.selected_upload_layers.remove(cBox.text())
          except Exception as e:
               print str(e)

现在我没有任何例外,并重新生成列表。我注意到新列表下面的旧列表,这意味着我没有正确删除布局(布局删除有各种问题)但我无法完全弄明白。把它们加起来。在这个具体的例子中,破坏和重新创建布局以及如何找出父子QObject关系的最方便方法是什么?困扰我的另一个问题是,每次打开设置选项卡时,lambda函数中都会出现逻辑转换,它会选择某些CheckBox。如何解决? 谢谢您的时间:))

1 个答案:

答案 0 :(得分:0)

我修好了。主要问题是removeItem方法,它没有按计划工作。虽然整件事情一团糟。我现在做了什么?我在类初始化时创建了复选框列表作为空列表并且条件正确我是第一次调用SettingsDock时检查它,还是在图层接口列表中更改了某些内容后调用它。代码如下所示。如果在评论中没有正确解释某些内容,请随意问我为什么这样做。干杯

    self.layers = qgis_api.get_layers()
    reduced_layers = []
    # reduced_layers is list variable which is populated with all layers
    # without redundant ones (same names of multiple files .shp/.shx/.dbf)
    # shapefile file format 
    for layer in self.layers:
        if layer.name() not in reduced_layers:
            reduced_layers.append(layer.name())

    # ScrollArea setup
    # Set up settingsDock.groupBox as a parent of Vertical layout
    # Check if Settings was clicked before api.upload would be handy for
    # that, scroll is QScrollArea and is added as widget with layout as
    # parent, after that I set up Scroll Content as widget with scroll
    # as parent, while scroll Layout is Vertical layout with scrollContent
    # as parent, but then i use scroll.setWidget method to define it as
    # a parent to scrollContent 
    if (api.selected_upload_layers == [] and
        api.project.layerTreeRoot().children() != []):
        self.tmp_layers = qgis_api.get_layers()
        self.layout = QVBoxLayout(self.settingsDock.groupBox)
        self.scroll = QScrollArea()
        # self.layout.addWidget(self.scroll)
        self.scroll.setWidgetResizable(True)
        self.scroll.setFixedHeight(111)
        self.layout.addWidget(self.scroll)
        self.scrollContent = QWidget(self.scroll)
        self.scrollLayout = QVBoxLayout(self.scrollContent)
        self.scroll.setWidget(self.scrollContent)

    # As self.checkboxes are initialized as empty list, here are we
    # generating a list of QCheckBox items with layer names(if there are
    # multiple layers with same name(shapefile format), only one will be
    # added as checkbox
    # After generating checkboxes list we use it to populate widgets,
    # QCheckBoxes in ScrollLayout, and set it in default as Checked
    # This is basically 1st time initialization
    if self.checkboxes == []:
        try:
            for i in range(0, len(self.layers)):
                if self.layers[i].name() not in map(lambda x: x.text(),
                                                    self.checkboxes):
                    self.checkboxes.append(QCheckBox('{}'.format(
                                            self.layers[i].name())))
            for i in range(0, len(self.checkboxes)):
                self.scrollLayout.addWidget(self.checkboxes[i])
                self.checkboxes[i].setChecked(True)
                api.selected_upload_layers = map(lambda x: x.text(),
                                                 self.checkboxes)
        except Exception as e:
            print str(e)

    # if checkboxes are different from layer list (that is generated) in
    # the moment of clicking show settings which basically indicates that
    # interface layer list has been chaged, we must update checkboxes
    # To update checkboxes list it's firstly deleted with ScrollContent
    elif map(lambda x: x.text(), self.checkboxes) != reduced_layers:
        num = self.scrollLayout.count()
        self.scrollLayout.removeWidget(self.scrollContent)
        self.scrollContent.deleteLater()
        self.scrollContent = QWidget(self.scroll)
        self.scrollLayout = QVBoxLayout(self.scrollContent)
        self.scroll.setWidget(self.scrollContent)
        try:
            self.checkboxes = []
            for i in range(0, len(self.layers)):
                if self.layers[i].name() not in map(lambda x: x.text(), self.checkboxes):
                    self.checkboxes.append(QCheckBox('{}'.format(
                                            self.layers[i].name())))
            for i in range(0, len(self.checkboxes)):
                self.scrollLayout.addWidget(self.checkboxes[i])
                self.checkboxes[i].setChecked(True)
        except Exception as e:
            print (e)

    for i in range(0, len(self.checkboxes)):
        self.checkboxes[i].stateChanged.connect(lambda checked, i=i:
                                            self.checkBoxChecked())

函数checkBoxChecked()如下:

    def checkBoxChecked(self):
    """Add functionality to ScrollArea checkboxes."""
    #print api.selected_upload_layers
    indices = []
    for i in range(0, len(self.checkboxes)):
        if self.checkboxes[i].isChecked():
            # print cBox.isChecked()
            print self.checkboxes[i].text() + " is selected"
            indices.append(i)
        else:
            print self.checkboxes[i].text() + " is deselected"

    api.selected_upload_layers = [map(lambda x: x.text(), self.checkboxes)[i] for i in indices]