title: How to disable an item in TreeWidget programmed in PYQT5
body: <p>I draw a tree widget and set up a list with many items in the widget.</p>
  
  <p><a href="https://i.stack.imgur.com/0ll1O.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/0ll1O.png" alt="enter image description here"></a></p>
  
  <p>The items are all checked by default. What I want is whenever a higher level item is unchecked then all children under the item should be disabled. My program successfully finds the items which should be disabled but the function (setDisabled) doesn't work. I tried the function (setHidden) but it's also not working.</p>
  
  <pre><code>from uitest import Ui_MainWindow
  from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel)
  
  Menulevel1 = ["Action1", "Action2", "Action3"]
  Menulevel2_1 = ["Action4", "Action6", "Action7"]
  Menulevel3_1_1 = ["Action8", "Action9", "Action10"]
  Menulevel3_1_2 = ["Action11", "Action12", "Action13"]
  Menulevel3_1_3 = ["Action14", "Action15", "Action16"]
  Menulevel2_2 = ["Action17", "Action18", "Action19"]
  Menulevel3_2_1 = ["Action20", "Action21", "Action22"]
  Menulevel3_2_2 = ["Action23", "Action24"]
  Menulevel3_2_3 = [""]
  Menulevel4_2_1_1 = ["Action25", "Action26", "Action27"]
  Menulevel4_2_2_1 = ["Action28", "Action29", "Action30"]
  Menulevel2_3 = ["Action31", "Action32", "Action33"]
  Menulevel3_3_1 = ["Action34", "Action35", "Action36"]
  Menulevel3_3_2 = ["Action37", "Action38", "Action39"]
  Menulevel3_3_3 = [""]
  
  class window(QMainWindow):
      def __init__(self, parent=None):
          super(window, self).__init__(parent)
          self.ui = Ui_MainWindow()
          self.ui.setupUi(self)
  
          self.treeload = False
          self.changedact_name = ""  # save the name of actions which will be dropped during trim process
          self.changedact_dir = ""
          self.changedact_pos = []
  
          menutree = self.ui.Menutree  # get the instance of tree widget
          # check whether the tree has been set up before,
          # if it has, there's no need to set up again (otherwise program will be stop)
          if not self.treeload:
              for i in range(len(Menulevel1)):
                  lvl1item = QTreeWidgetItem(menutree)  # get the tree widget instance
                  lvl1item.setText(0, Menulevel1[i])  # set the first level text to be actions in menu level 1
                  # set up the first level elements to be a three state check box
                  # three state: checked, unchecked and partiallychecked, all used in handleItemChanged function
                  lvl1item.setFlags(lvl1item.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
                  # lvl1item.setDisabled(True)
                  lvl2 = eval("Menulevel2_%d" % (i + 1))  # set up a command for adding item of second level
                  for j in range(len(lvl2)):  # loop to add menu level 2 action name
                      lvl2item = QTreeWidgetItem(lvl1item)  # set up the parent level
                      # set up the child to be selectable
                      # If the child's checkbox isn't given a state, the checkbox element does not appear
                      lvl2item.setFlags(lvl2item.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
                      lvl2item.setText(0, lvl2[j])  # set up the item text to action name of menu level 2
                      lvl2item.setCheckState(0, Qt.Checked)  # set the item default to checked
                      # set up a command for adding item of third level
                      lvl3 = eval("Menulevel3_%d_%d" % (i + 1, j + 1))
                      for k in range(len(lvl3)):  # loop to add menu level 3 action name
                          if lvl3[k] is not "":  # check whether there is action in menu level 3
                              lvl3item = QTreeWidgetItem(lvl2item)  # set up the parent level
                              lvl3item.setFlags(lvl3item.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
                              lvl3item.setText(0, lvl3[k])  # set up the item text to action name of menu level 3
                              lvl3item.setCheckState(0, Qt.Checked)  # set the item default to checked
                              # check whether the action is one of the first three actions, if it is,
                              # the action cannot be changed
                              try:  # try add menu level 4 action name
                                  # set up the command
                                  lvl4 = eval("Menulevel4_%d_%d_%d" % (i + 1, j + 1, k + 1))
                                  for l in range(len(lvl4)):  # set up the loop
                                      lvl4item = QTreeWidgetItem(lvl3item)  # set up the parent
                                      lvl4item.setFlags(lvl4item.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
                                      lvl4item.setText(0, lvl4[l])
                                      lvl4item.setCheckState(0, Qt.Checked)
                              except:  # if there's no action in menu level 4
                                  pass  # continue the rest
              menutree.expandAll()  # expand all items on the tree
              # put the tree load variable to true, whenever get in this section again there's no need to build tree again
              # addition: whenever build the tree if try to build again, the program will
              # stop at lvl1item.setText(0, Menulevel1_EN[i])
              self.treeload = True
              # whenever a checkbox is changed, handle item changed function will be called
              # and the item will be determined
              menutree.itemChanged.connect(self.handleItemChanged)
  
      # the function to process changed check box in tree widget
      def handleItemChanged(self, item, column):
          if item.checkState(column) == Qt.Unchecked:  # determine whether the checkbox of item is unchecked
              self.changedact_name = item.text(column) + ";"  # save the text of item (action name) in global variable
              self.changedact_dir = "Drop"  # set the change direction variable to drop - drop the action
          # determine whether the checkbox of item is partiallychecked, usually the higher level will be the status
          elif item.checkState(column) == Qt.PartiallyChecked:
              # save the text of item (action name) in global variable, help determine which action is changed later
              self.changedact_name += item.text(column) + ";"
          elif item.checkState(column) == Qt.Checked:  # determine whether the checkbox of item is unchecked
              self.changedact_name += item.text(column) + ";"  # save the text of item (action name) in global variable
              # set the change direction variable to add - add the action which is dropped before
              self.changedact_dir = "Add"
  
          if item.text(column) in Menulevel1:  # check whether the item reaches the menu level 1 - the top level
              # actindex = Menulevel1_EN.index(item.text(column))
              # call find changed action function to determine the status of which action is changed
              self.findChangedAction()
              self.changedact_name = ""  # clear the variable for saving new changed item
              self.changedact_dir = ""  # clear the variable for saving new changed direction
  
  
      def findChangedAction(self):  # function of determining the status of which action is changed
          changedactionlist = self.changedact_name.split(";")  # using ; to separate the variable into list
          changedaction = list(filter(None, changedactionlist))  #
          changedaction.reverse()
          length = len(changedaction)  # determine the length of the list
          # because the last item in the list is empty, the second last item will be the action in menu level 1
          # determine the changed item is in which menu level
          lvl1pos = Menulevel1.index(changedaction[0]) + 1
          lvl2 = lvl3 = lvl4 = ""
          lvl2pos = lvl3pos = lvl4pos = 0
          if length &gt;1:
              lvl2 = eval("Menulevel2_%d" %lvl1pos)
              lvl2pos = lvl2.index(changedaction[1])+1
              try:
                  lvl3 = eval("Menulevel3_%d_%d" % (lvl1pos, lvl2pos))
                  lvl3pos = lvl3.index(changedaction[2]) + 1
                  try:
                      lvl4 = eval("Menulevel4_%d_%d_%d" % (lvl1pos, lvl2pos, lvl3pos))
                      lvl4pos = lvl4.index(changedaction[-1])+1
                  except:
                      pass
              except:
                  pass
          else:
              lvl2 = ""
              lvl2pos = 0
              lvl3 = ""
              lvl3pos = 0
              lvl4 = ""
              lvl4pos = 0
              lvl2 = eval("Menulevel2_%d" %lvl1pos)
  
          fullpos = lvl1pos * 1000 + lvl2pos * 100 + lvl3pos * 10 + lvl4pos
          threepos = lvl1pos * 1000 + lvl2pos * 100 + lvl3pos * 10
          twopos = lvl1pos * 1000 + lvl2pos * 100
          onepos = lvl1pos * 1000
          if fullpos == threepos and lvl4 != "":
              for i in lvl4:
                  disableitem = self.ui.Menutree.findItems(i, Qt.MatchExactly | Qt.MatchRecursive, 0)
                  try:
                      disableitem.setDisabled(True)
                  except:
                      pass
          elif fullpos == twopos and lvl3 != "":
              for i in lvl3:
                  disableitem = self.ui.Menutree.findItems(i, Qt.MatchExactly | Qt.MatchRecursive, 0)
                  try:
                      disableitem.setDisabled(True)
                  except:
                      pass
  
  
  if __name__ == "__main__":
      app = QApplication([])
      gui = window()
      gui.show()
      app.exec_()
  </code></pre>
  
  <p>And the UI code is here:</p>
  
  <pre><code>from PyQt5 import QtCore, QtGui, QtWidgets
  
  class Ui_MainWindow(object):
      def setupUi(self, MainWindow):
          MainWindow.setObjectName("MainWindow")
          MainWindow.resize(816, 549)
          self.centralwidget = QtWidgets.QWidget(MainWindow)
          self.centralwidget.setObjectName("centralwidget")
          self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
          self.gridLayout.setObjectName("gridLayout")
          self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
          self.scrollArea.setWidgetResizable(True)
          self.scrollArea.setObjectName("scrollArea")
          self.scrollAreaWidgetContents = QtWidgets.QWidget()
          self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 796, 440))
          self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
          self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
          self.verticalLayout.setContentsMargins(0, 0, 0, 0)
          self.verticalLayout.setObjectName("verticalLayout")
          self.Menutree = QtWidgets.QTreeWidget(self.scrollAreaWidgetContents)
          self.Menutree.setObjectName("Menutree")
          self.Menutree.header().setVisible(False)
          self.verticalLayout.addWidget(self.Menutree)
          spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
          self.verticalLayout.addItem(spacerItem)
          self.groupBox = QtWidgets.QGroupBox(self.scrollAreaWidgetContents)
          self.groupBox.setTitle("")
          self.groupBox.setObjectName("groupBox")
          self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox)
          self.horizontalLayout.setObjectName("horizontalLayout")
          spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
          self.horizontalLayout.addItem(spacerItem1)
          self.Previous = QtWidgets.QPushButton(self.groupBox)
          font = QtGui.QFont()
          font.setPointSize(14)
          font.setBold(True)
          font.setWeight(75)
          self.Previous.setFont(font)
          self.Previous.setObjectName("Previous")
          self.horizontalLayout.addWidget(self.Previous)
          spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
          self.horizontalLayout.addItem(spacerItem2)
          self.Next = QtWidgets.QPushButton(self.groupBox)
          font = QtGui.QFont()
          font.setPointSize(14)
          font.setBold(True)
          font.setWeight(75)
          self.Next.setFont(font)
          self.Next.setObjectName("Next")
          self.horizontalLayout.addWidget(self.Next)
          spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
          self.horizontalLayout.addItem(spacerItem3)
          self.Next_Save = QtWidgets.QPushButton(self.groupBox)
          font = QtGui.QFont()
          font.setPointSize(14)
          font.setBold(True)
          font.setWeight(75)
          self.Next_Save.setFont(font)
          self.Next_Save.setObjectName("Next_Save")
          self.horizontalLayout.addWidget(self.Next_Save)
          spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
          self.horizontalLayout.addItem(spacerItem4)
          self.verticalLayout.addWidget(self.groupBox)
          self.scrollArea.setWidget(self.scrollAreaWidgetContents)
          self.gridLayout.addWidget(self.scrollArea, 0, 0, 1, 1)
          MainWindow.setCentralWidget(self.centralwidget)
          self.menubar = QtWidgets.QMenuBar(MainWindow)
          self.menubar.setGeometry(QtCore.QRect(0, 0, 816, 21))
          self.menubar.setObjectName("menubar")
          MainWindow.setMenuBar(self.menubar)
          self.statusbar = QtWidgets.QStatusBar(MainWindow)
          self.statusbar.setObjectName("statusbar")
          MainWindow.setStatusBar(self.statusbar)
          self.TBlevel1 = QtWidgets.QToolBar(MainWindow)
          sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
          sizePolicy.setHorizontalStretch(0)
          sizePolicy.setVerticalStretch(0)
          sizePolicy.setHeightForWidth(self.TBlevel1.sizePolicy().hasHeightForWidth())
          self.TBlevel1.setSizePolicy(sizePolicy)
          font = QtGui.QFont()
          font.setPointSize(14)
          self.TBlevel1.setFont(font)
          self.TBlevel1.setObjectName("TBlevel1")
          MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.TBlevel1)
          self.TBlevel2 = QtWidgets.QToolBar(MainWindow)
          font = QtGui.QFont()
          font.setPointSize(12)
          self.TBlevel2.setFont(font)
          self.TBlevel2.setObjectName("TBlevel2")
          MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.TBlevel2)
          MainWindow.insertToolBarBreak(self.TBlevel2)
          self.TBlevel3 = QtWidgets.QToolBar(MainWindow)
          font = QtGui.QFont()
          font.setPointSize(10)
          self.TBlevel3.setFont(font)
          self.TBlevel3.setObjectName("TBlevel3")
          MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.TBlevel3)
          MainWindow.insertToolBarBreak(self.TBlevel3)
          self.TBlevel4 = QtWidgets.QToolBar(MainWindow)
          self.TBlevel4.setObjectName("TBlevel4")
          MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.TBlevel4)
          MainWindow.insertToolBarBreak(self.TBlevel4)
  
          self.retranslateUi(MainWindow)
          QtCore.QMetaObject.connectSlotsByName(MainWindow)
  
      def retranslateUi(self, MainWindow):
          _translate = QtCore.QCoreApplication.translate
          MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
          self.Previous.setText(_translate("MainWindow", "Previous"))
          self.Next.setText(_translate("MainWindow", "Next"))
          self.Next_Save.setText(_translate("MainWindow", "Next and Save"))
          self.TBlevel1.setWindowTitle(_translate("MainWindow", "toolBar"))
          self.TBlevel2.setWindowTitle(_translate("MainWindow", "toolBar"))
          self.TBlevel3.setWindowTitle(_translate("MainWindow", "toolBar_2"))
          self.TBlevel4.setWindowTitle(_translate("MainWindow", "toolBar"))
  
  
  if __name__ == "__main__":
      import sys
      app = QtWidgets.QApplication(sys.argv)
      MainWindow = QtWidgets.QMainWindow()
      ui = Ui_MainWindow()
      ui.setupUi(MainWindow)
      MainWindow.show()
      sys.exit(app.exec_())
  </code></pre>
  
  <p>I read that answer(<a href="https://stackoverflow.com/questions/31342228/pyqt-tree-widget-adding-check-boxes-for-dynamic-removal">PyQt Tree Widget, adding check boxes for dynamic removal</a>) before I ask. My question is different because as I described above whenever I unchecked the parent item I want to disable the children it has. I did really use parent.setCheckState(0, Qt.Unchecked), but whenever I find out which parent item is unchecked and try to disable the children, my program always crashed. I don't know why. So that's why I post my code to here and ask for help. Can someone help me out? Thank you!</p>