动态添加qtableview到动态创建的标签页(qtabwidget)

hwamh0ep  于 2021-07-13  发布在  Java
关注(0)|答案(0)|浏览(489)

我正在尝试在运行时创建一系列qtableview,并将它们添加到多页qtabwidget的新创建页面中。
一切似乎都很顺利,但qtableview没有出现。qtabwidget会被清零(重置为无页面)和重新整修(…)(至少看起来是这样),这取决于组合框的选择(以及其中相关的字典)。
我还使用委托回调将一列复选框包含到qtableview中(感谢https://stackoverflow.com/a/50314085/7710452),单独使用效果很好。
这是密码。主窗口
按照eyllanesc的建议进行编辑,以下是独立模块:

"""
    qt5 template
"""
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 + " Setup")
        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)
            # next line like this crashes
            # with no widget passed no QTableView is visible, tabs are ok
            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('E:\\Python_Scripts\\Backmetal_Running_Hours_Setup\\config.ini')
    app = qtw.QApplication([sys.argv])
    w = MainWindow(config, 'config.ini',
                   'E:\\Python_Scripts\\Backmetal_Running_Hours_Setup\\proj\\test_setup_1.proj')

    sys.exit(app.exec_())

下面是要添加复选框列的外部选项:

class CheckBoxDelegate(QtWidgets.QItemDelegate):
    """
    A delegate that places a fully functioning QCheckBox cell of the column to which it's applied.
    """
    def __init__(self, parent):
        QtWidgets.QItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        """
        Important, otherwise an editor is created if the user clicks in this cell.
        """
        return None

    def paint(self, painter, option, index):
        """
        Paint a checkbox without the label.
        """
        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() & QtCore.Qt.ItemIsEditable) > 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)



第一张图显示了qtdesigner中的布局,第二张图显示了避免崩溃时的结果(emtpy选项卡)。qtabwidget在归零或缩放回所需的选项卡数量方面没有问题,只是我不知道如何浏览qtabview。
顺便说一下:通过pycharm调试程序检查,一旦populatin方法返回两个对象数组(列表) self.tableViews 以及 self.tabs 保持正确数量的物体,同时保持“碰撞”i的姿势: self.tableViews.append(qtw.QTableView(**self.tabs[tabs_index]**)) 两个列表已填写。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题