title: Dynamically add QTableView to dynamically created tab pages (QTabWidget) [SOLVED]
body: <p>I am trying to have a series of QTableView created at runtime and added to newly created pages of a multipage QTabWidget.</p>
  <p>All seems to go fine, but the QTableView don't show up.
  The QTabWidget gets zeroed (reset to no pages) and refurbished (...) flawlessly (at least it looks like so) depending on the selection of a combobox (and the dictionaries therein related).</p>
  <p>I am also using a delegate callback to include a column of checkboxes to the QTableView (thanks to <a href="https://stackoverflow.com/a/50314085/7710452">https://stackoverflow.com/a/50314085/7710452</a>), which works fine stand alone.</p>
  <p>Here is the code.
  Main Window</p>
  <p><strong>EDIT</strong>
  as recommended by eyllanesc, here is the standalone module (jump to the end of the post for details on the part I think is problematic):</p>
  <pre><code>&quot;&quot;&quot;
      qt5 template
  &quot;&quot;&quot;
  import os
  import sys
  from PyQt5 import QtWidgets as qtw
  from PyQt5 import QtCore as qtc
  from PyQt5 import QtGui as qtg
  from PyQt5 import uic
  from configparser import ConfigParser, ExtendedInterpolation
  from lib.SearchControllers import findGuis, get_controller_dict, show_critical, show_exception
  import resources.resources
  from lib.CheckBoxesDelegate import CheckBoxDelegate
  myForm_2, baseClass = uic.loadUiType('./forms/setup.ui')
  class MainWindow(baseClass):
  
      def __init__(self, config_obj: ConfigParser,
                   config_name: str,
                   proj_name: str,
                   *args,
                   **kwargs):
  
          super().__init__(*args, **kwargs)
          self.ui = myForm_2()
          self.ui.setupUi(self)
  
          # your code begins here
          self.setWindowTitle(proj_name + &quot; Setup&quot;)
          self.ui.logo_lbl.setPixmap(qtg.QPixmap(':/logo_Small.png'))
          self.config_obj = config_obj
          self.config_name = config_name
          self.proj_filename = proj_name
          self.proj_config = ConfigParser(interpolation=ExtendedInterpolation())
          self.proj_config.read(proj_name)
          self.guis_dict = {}
          self.components = {}
          self.cdp_signals = {}
          self.root_path = self.config_obj['active']['controllers']
          self.tableViews = []
          self.tabs = []
          self.iniControllersBox()
          self.setActSignals()
          self.load_bulk()
          self.set_signals_table()
          self.update_CurController_lbl()
          self.update_ControllersTab()    # here is where the action gets hot
  
          # your code ends here
  
          self.show() # here crashes if I passed the new tab to the instance of
                      # QTabView. otherwise it shows empty tabs
  #########################################################
  
      def load_bulk(self):
          # get the list of running components into a dictionary
          for i in self.list_controllers:
              i_path = os.path.join(self.root_path, i)
              print(i)
              self.components[i] = get_controller_dict(i_path,
                                                       self.config_obj,
                                                       'Application.xml',
                                                       'Subcomponents/Subcomponent',
                                                       'Name',
                                                       'src')
  
              for j in self.components[i]:
                  print(j)
                  signals_key = (i , j)
                  tgt = os.path.join(self.root_path, self.components[i][j])
                  self.cdp_signals[signals_key] = get_controller_dict(i_path,
                                                                      self.config_obj,
                                                                      self.components[i][j],
                                                                      'Signals/Signal',
                                                                      'Name',
                                                                      'Type',
                                                                      'Routing')
  
  
      def set_signals_table(self):
          self.ui.MonitoredDevicesTable.setHorizontalHeaderItem(0, qtw.QTableWidgetItem('GUI caption'))
          self.ui.MonitoredDevicesTable.setHorizontalHeaderItem(1, qtw.QTableWidgetItem('Monitored Signal'))
  
      def setActSignals(self):
          self.ui.controllersBox.currentIndexChanged.connect(self.update_guis_list)
          self.ui.controllersBox.currentIndexChanged.connect(self.update_CurController_lbl)
          self.ui.controllersBox.currentIndexChanged.connect(self.update_ControllersTab)
  
      def update_ControllersTab(self):
          self.ui.componentsTab.clear()   # this is the QTabWidget
          self.tabs = []
          self.tableViews = []
          curr_controller = self.ui.controllersBox.currentText()
          for i in self.components[curr_controller]:
              if len(self.cdp_signals[curr_controller, i]) == 0:
                  continue
              self.tabs.append(qtw.QWidget())
              tabs_index = len(self.tabs) - 1
              header_labels = ['', 'Signal', 'Type', 'Routing', 'Input']
              model = qtg.QStandardItemModel(len(self.cdp_signals[curr_controller, i]), 5)
              model.setHorizontalHeaderLabels(header_labels)
  # in the next line I try to create a new QTableView passing
  # the last tab as parameter, in the attempt to embed the QTableView
  # into the QWidget Tab 
  
              self.tableViews.append(qtw.QTableView(self.tabs[tabs_index])) 
              tbw_Index = len(self.tableViews) - 1
              self.tableViews[tbw_Index].setModel(model)
              delegate = CheckBoxDelegate(None)
              self.tableViews[tbw_Index].setItemDelegateForColumn(0, delegate)
              rowCount = 0
              for row in self.cdp_signals[curr_controller, i]:
                  for col in range(len(self.cdp_signals[curr_controller, i][row])):
                      index = model.index(rowCount, col, qtc.QModelIndex())
                      model.setData(index, self.cdp_signals[curr_controller, i][row][col])
              try:
                  self.ui.componentsTab.addTab(self.tabs[tabs_index], i) # no problems, some controllers ask up to
              except Exception as ex:
                  print(ex)
  
      def update_CurController_lbl(self):
          self.ui.active_controller_lbl.setText(self.ui.controllersBox.currentText())
  
      def iniControllersBox(self):
          self.list_controllers = [os.path.basename(f.path) for f in os.scandir(self.root_path) if f.is_dir() and str(
              f.path).upper().endswith('NC')]
          self.ui.controllersBox.addItems(self.list_controllers)
          for i in range(self.ui.controllersBox.count()):
              self.ui.controllersBox.setCurrentIndex(i)
              newKey = self.ui.controllersBox.currentText()
              cur_cntrlr = os.path.join(self.config_obj['active']['controllers'], self.ui.controllersBox.currentText())
              self.guis_dict[newKey] = findGuis(cur_cntrlr, self.config_obj)
          self.ui.controllersBox.setCurrentIndex(0)
          self.update_guis_list()
  
      def update_guis_list(self, index=0):
          self.ui.GuisListBox.clear()
          self.ui.GuisListBox.addItems(self.guis_dict[self.ui.controllersBox.currentText()])
  
  if __name__ == '__main__':
      config = ConfigParser()
      config.read('./config.ini')
      app = qtw.QApplication([sys.argv])
      w = MainWindow(config, './config.ini',
                     './test_setup_1.proj')
                     
      sys.exit(app.exec_())
  </code></pre>
  <p>and here the external to add the checkboxes column:</p>
  <pre><code>class CheckBoxDelegate(QtWidgets.QItemDelegate):
      &quot;&quot;&quot;
      A delegate that places a fully functioning QCheckBox cell of the column to which it's applied.
      &quot;&quot;&quot;
      def __init__(self, parent):
          QtWidgets.QItemDelegate.__init__(self, parent)
  
      def createEditor(self, parent, option, index):
          &quot;&quot;&quot;
          Important, otherwise an editor is created if the user clicks in this cell.
          &quot;&quot;&quot;
          return None
  
      def paint(self, painter, option, index):
          &quot;&quot;&quot;
          Paint a checkbox without the label.
          &quot;&quot;&quot;
          self.drawCheck(painter, option, option.rect, QtCore.Qt.Unchecked if int(index.data()) == 0 else QtCore.Qt.Checked)
  
      def editorEvent(self, event, model, option, index):
          '''
          Change the data in the model and the state of the checkbox
          if the user presses the left mousebutton and this cell is editable. Otherwise do nothing.
          '''
          if not int(index.flags() &amp; QtCore.Qt.ItemIsEditable) &gt; 0:
              return False
  
          if event.type() == QtCore.QEvent.MouseButtonRelease and event.button() == QtCore.Qt.LeftButton:
              # Change the checkbox-state
              self.setModelData(None, model, index)
              return True
  
          if event.type() == QtCore.QEvent.MouseButtonPress or event.type() == QtCore.QEvent.MouseMove:
              return False
  
          return False
  
  
      def setModelData (self, editor, model, index):
          '''
          The user wanted to change the old state in the opposite.
          '''
          model.setData(index, 1 if int(index.data()) == 0 else 0, QtCore.Qt.EditRole)
  </code></pre>
  <p><a href="https://i.stack.imgur.com/6pjtS.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6pjtS.png" alt="the rough setup of the UI in qtdesigner is like this:" /></a></p>
  <p><a href="https://i.stack.imgur.com/l9r0j.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/l9r0j.png" alt="what I am achieving so far is this:" /></a></p>
  <p>The 1st picture shows the layout in QTDesigner, the 2nd the result (emtpy tabs) when avoiding the crashing.</p>
  <p>the QTabWidget has no problems in zeroing, or scale up, back to as many tab as I need, it's just that I have no clue on how to show the QTabview. My approach was to try to embed the QTabView in the tabpage passing it as parameter to the line creating the new QTabView.</p>
  <p>Since I am using rather convoluted dictionaries, calling an XML parser to fill them up, not to mention the config files, I know even this version of my script is hardly reproduceable/runnable.</p>
  <p>If someone had the patience of focusing on the <code>update_ControllersTab</code> method though, and tell me what I am doing wrong handling the QWidgets, it'd be great.</p>
  <p>Again the basic idea is to clear the QTabWidget any time the user selects a different controller (combo box on the left):</p>
  <pre><code>    self.ui.componentsTab.clear()   # this is the QTabWidget
      self.tabs = []                  # list to hold QTabView QWidgets (pages) throughout the scope
      self.tableViews = []            # list to hold QTabView(s) thorughout the scope
  </code></pre>
  <p>count how many tabs (pages) and hence embedded TabViews I need with the new controllers selected.
  and then for each tab needed:</p>
  <p>create a new tab (page)</p>
  <pre><code>    self.tabs.append(qtw.QWidget())
      tabs_index = len(self.tabs) - 1
  </code></pre>
  <p>create a new QTabView using a model:</p>
  <pre><code>    header_labels = ['', 'Signal', 'Type', 'Routing', 'Input']
      model = qtg.QStandardItemModel(len(self.cdp_signals[curr_controller, i]), 5)
      model.setHorizontalHeaderLabels(header_labels)
      self.tableViews.append(qtw.QTableView(self.tabs[tabs_index]))
      tbw_Index = len(self.tableViews) - 1
      self.tableViews[tbw_Index].setModel(model)
  </code></pre>
  <p>populate the TableView with data, and then finally add the tab widget (with the suppposedly embedded QTableView to the  QTabWidget (the <code>i</code> argument is a string from my dbases Names:</p>
  <pre><code>    self.ui.componentsTab.addTab(self.tabs[tabs_index], i)
  </code></pre>
  <p>This method is called also by the <code>__init__</code> to initialize and apparently all goes error free, until the last '<strong>init</strong>' statement:</p>
  <pre><code>`self.show()`
  </code></pre>
  <p>at which point the app crashes with:</p>
  <pre><code>Process finished with exit code 1073741845
  </code></pre>
  <p>on the other hand, if here instead of trying to embed the QTableView:</p>
  <pre><code>self.tableViews.append(qtw.QTableView(self.tabs[tabs_index]))
  </code></pre>
  <p>I omit the parameter, that is:</p>
  <pre><code>self.tableViews.append(qtw.QTableView())
  </code></pre>
  <p>the app doesn't crash anymore, but of course no QtableViews are shown, only empty tabpages:
  <a href="https://i.stack.imgur.com/cSuXK.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/cSuXK.png" alt="enter image description here" /></a></p>