2017-09-05 2 views
0

저는 현재 Python 2.7 및 PyQt 4로 QGIS 용 플러그인을 개발 중입니다. 플러그인에서 사용자가 설정 탭을 열 때마다 재생성 될 맵 레이어 목록 (항목 목록 일 수 있음)이 있어야합니다. . 설정 버튼을 클릭 할 때마다 재생성되는 QCheckBoxes의 확인 가능한 목록을 만들 수 있었지만 여전히 훌륭하고 기능적인 것은 아닙니다. 내가 알아 낸대로, 내 문제는 주로 부모 - 자식 관계와 레이아웃 삭제입니다.동적으로 변경 가능한 QCheckBox 목록

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 내가 예외를하지 않으며, 목록이 재생됩니다 다음과 같이

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는()입니다. 새 레이아웃 아래에 오래된 목록이 있다는 것을 알았습니다. 즉, 레이아웃을 올바르게 삭제하지 않고 있습니다 (레이아웃 삭제에 대한 다양한 질문이 있음). 그러나 완전히 이해할 수는 없습니다. 그것을 요 ​​약하기. 이 구체적인 예에서 레이아웃을 파괴하고 재창조하는 가장 편리한 방법과 부모 - 자식 QObject 관계를 파악하는 방법은 무엇입니까? 그리고 저를 귀찮게하는 또 하나의 질문은 새로운 설정 탭이 열릴 때마다 특정 CheckBox를 선택하는 데 많은 어려움을 겪게되는 람다 함수에서의 논리 전환이있는 것 같습니다. 그것을 고치는 방법? 시간 내 주셔서 감사합니다.

답변

0

수정했습니다. 주요 문제는 계획대로 작동하지 않은 removeItem 메소드였습니다. 모든 것이 엉망 이었지만. 나는 지금 무엇을 했는가? 빈 목록으로 클래스 초기화에서 checkboxes 목록을 만들었고 정확한 조건을 확인하기 위해 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]