2017-09-05 65 views
0

我目前正在为Python 2.7和PyQt 4开发QGIS插件。我的插件应该有每次打开“设置”选项卡时都会重新生成的地图图层的可检查列表(可能是项目列表,无关) 。尽管我设法创建了QCheckBoxes的可检查列表,每次单击“设置”按钮时都会重新生成QCheckBoxes,但它仍然远离功能良好的QCheckBox。正如我想到的,我的问题主要是亲子关系和布局删除。可动态更改的QCheckBox列表

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) 

Alhtough现在我没有得到任何的异常,并且列表再生。我注意到新列表下方的旧列表,这意味着我没有正确删除布局(布局删除有各种问题),但我无法完全弄清楚。把它们加起来。在这个具体的例子中,破坏和重建布局以及如何计算父子QObject关系的最方便的方法是什么?还有一个让我困扰的问题是,随着设置选项卡的每一次新的打开,lambda函数中似乎都会进行逻辑恢复,从而为选择某个CheckBox执行所有繁重的操作。如何解决这个问题? 谢谢你的时间:)

回答

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]