首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PySide TableView和变体数据显示角色不显示

PySide TableView和变体数据显示角色不显示
EN

Stack Overflow用户
提问于 2015-12-03 02:28:23
回答 1查看 1.3K关注 0票数 0

我有这段代码,当我在PyQt中运行它时,它工作得很好,但是当我在pyside运行它时,情况就变得很糟糕了。我得到了我应该得到的所有列和行,如果我通过脚本访问它们并获取数据,每个单元格都会说明它应该做什么。但是,即使我将这些设置为显示角色,表中也没有显示文本。头中没有,任何单元格中都没有。我不知所措!

( NulLVariant()只是返回None或QVariant(),这取决于是否在pyside或pyqt上)

此模型的目的是将Dicts列表传递到addRows,并使用dict生成列。

代码语言:javascript
运行
复制
class CustomTableModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None, parentTable=None):
        """
        Custom data model for holding table data.

        :param parent: The parent widget/layout so that this data model gets deleted properly on close.
        :param parentTable: the table that is using this data. This is used to get the font metrics of the table
        display font.
        """
        super(CustomTableModel, self).__init__(parent)

        self.parent_table = parentTable
        self.auto_resize = False
        self._avg_font_w = 5
        self._resize_data = defaultdict(int)

        self.items = []
        self.headers = []

    def setParentTable(self, widget):
        """
        Sets the parent table widget so that we can get its font metrics for setting our column width with autoResize.
        :param widget: TableViewWidget
        :raise TypeError:
        """
        if not isinstance(widget, QtGui.QTableView):
            raise TypeError('Must be a TableView item')

        self.parent_table = widget

    def setAutoResize(self, b):
        """
        Turns on or off auto resize for the table. This gathers the font metrics of the parent table, and then loops
        over any current data, or newly added data (including table headers) to get the widest item, and sets the
        column width to fit this.
        :param b: bool
        :raise AttributeError:
        """
        if not self.parent_table:
            raise AttributeError('You must call setParentTable first to set the parent TableView item')

        self.auto_resize = b
        if b:
            self._autoAllResizeData()
            self._doColumnResize()
        else:
            self._resize_data = dict()

    def updateSize(self):
        """
        Force the table size to update to the current size data.
        """
        self._doColumnResize()

    def updateSizeData(self):
        """
        Force an update/regathering of all the size data for each row and column.
        """
        self._autoAllResizeData(True)
        self._doColumnResize()

    def _doColumnResize(self):
        for i in range(len(self.headers)):
            txt = self.headers[i]
            self.parent_table.setColumnWidth(i, self._resize_data.get(txt))

    def _getKeyList(self):
        if self.headers:
            return self.headers
        elif self.items:
            return sorted(self.items[0].keys())

    def _getTableFontWidth(self):
        self._avg_font_w = self.parent_table.fontMetrics().averageCharWidth()

    def _autoAllResizeData(self, reset=False):
        if not self._resize_data or reset is True:
            self._resize_data = defaultdict(int)

            key_list = self._getKeyList()
            for header in key_list:
                header_width = len(header) * (self._avg_font_w * 1.55)
                if header_width > self._resize_data[header]:
                    self._resize_data[header] = header_width

                for item in self.items:
                    value = item.get(header)
                    width = len(str(value)) * self._avg_font_w
                    if width > self._resize_data[header]:
                        self._resize_data[header] = width

    def _autoSingleResizeData(self, data):
        key_list = self._getKeyList()
        for header in key_list:
            value = data.get(header)
            if value:
                width = len(str(value)) * self._avg_font_w
                if width > self._resize_data[header]:
                    self._resize_data[header] = width

    def setHeaders(self, items):
        """
        This allows you to set your header item text
        :param items: a list of header text, ie ['Name', 'Email', 'Department']
        """
        lastCount = self.columnCount(QtCore.QModelIndex())
        self.headers = items

        self.beginRemoveColumns(QtCore.QModelIndex(), 0, lastCount)
        for x in range(lastCount):
            self.removeColumn(x)
        self.endRemoveColumns()

        self.beginInsertColumns(QtCore.QModelIndex(), 0, len(items)-1)
        self.endInsertColumns()

    def addRow(self, data):
        """
        Accepts a dict of data to add to the data model.
        :param data: dict (this should match the same key length/names as the other data in the table.)
        """
        row = len(self.items)
        self.beginInsertRows(QtCore.QModelIndex(), row, row)
        self.items.append(data)
        self.endInsertRows()

        if self.auto_resize:
            self._autoSingleResizeData(data)
            self._doColumnResize()

    def addRows(self, data):
        """
        Accepts a list of dicts to add them all to the table, with each list index being a row, and each dict key
        a column.
        :param data: list of dicts
        :raise ValueError:
        """
        if not isinstance(data, list) or not isinstance(data[0], dict):
            raise ValueError('input must be a list of dicts!')

        start_row = len(self.items)
        end_row = len(data) + start_row - 1

        self.beginInsertRows(QtCore.QModelIndex(), start_row, end_row)
        self.items.extend(data)
        self.endInsertRows()

        if self.auto_resize:
            for item in data:
                self._autoSingleResizeData(item)
                self._doColumnResize()

    def removeRow(self, row):
        """
        Remove the row at index 'row'.
        :param row: int
        """
        self.beginRemoveRows(QtCore.QModelIndex(), row, row)
        self.items.pop(row)
        self.endRemoveRows()

    def clear(self):
        """
        Clear all table data and start fresh.
        """
        rows = self.rowCount(QtCore.QModelIndex())
        self.beginRemoveRows(QtCore.QModelIndex(), 0, rows)
        self.items = []
        self.endRemoveRows()

        cols = self.columnCount(QtCore.QModelIndex())
        self.beginRemoveColumns(QtCore.QModelIndex(), 0, cols)
        self.headers = []
        self.endRemoveColumns()

    def rowCount(self, QModelIndex):
        """
        Return the row count.
        :param QModelIndex:
        :return:
        """
        return len(self.items)

    def columnCount(self, QModelIndex):
        """
        Return the column count (default 1)
        :param QModelIndex:
        :return:
        """
        try:
            return len(self.items[0].keys())
        except:
            return 1

    def data(self, index, role):
        """
        Accepts a QModelIndex and a Qt.Role and returns the data at the given modelIndex.
        :param index: QModelIndex
        :param role: QtCore.Qt.<Role>
        :return:
        """
        row = index.row()
        col = index.column()
        if role == QtCore.Qt.DisplayRole:
            key_list = self._getKeyList()
            return QtCore.QVariant(str(self.items[row][key_list[col]]))

        return NullVariant()

    def intGetData(self, row, col):
        """
        Gets the data at 'row' and 'col'.
        :param row: int
        :param col: int
        :return: QVariant() data.
        """
        try:
            key_list = self._getKeyList()
            return QtCore.QVariant(str(self.items[row][key_list[col]]))
        except:
            return NullVariant()

    def headerData(self, section, orientation, role):
        """
        Sets the header data based on our header key list.

        :param section: section header
        :param orientation: orientation
        :param role: Qt<Role>
        :return:
        """
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                if not self.items:
                    if section == 0:
                        return QtCore.QVariant(str("Column 1"))

                else:
                    key_list = self._getKeyList()
                    try:
                        return QtCore.QVariant(str(key_list[section]))
                    except:
                        return QtCore.QVariant('No Data')

        return NullVariant()


class CustomSortModel(QtGui.QSortFilterProxyModel):
    def __init__(self, parent=None):
        """
        Custom QSortFilterProxyModel to allow sorting and filtering of our custom data model.
        :param parent: parent so that this model is deleted properly upon close.
        """
        super(CustomSortModel, self).__init__(parent)

        self.countAllColumns = False
        self._sortingColumn = 0

    def filterAcceptsRow(self, sourceRow, sourceParent):
        """
        Overriding how we choose what rows match our input filter text.

        :param sourceRow: row index in question
        :param sourceParent: QModelIndex
        :return: bool (accepted or not)
        """
        txt = ''

        if self.countAllColumns:
            for x in range(len(self.sourceModel().headers)):
                txt += self.sourceModel().intGetData(sourceRow, x).toString()

        else:
            txt = self.sourceModel().intGetData(sourceRow, self._sortingColumn).toString()

        if self.filterRegExp().pattern():
            b = bool(re.search(str(self.filterRegExp().pattern()), str(txt)))
        else:
            b = bool(re.search('.*', str(txt)))

        return b

    def setFilterKeyColumn(self, col):
        """
        Sets which column index you want the filter to apply to. -1 or less means we search all columns - otherwise,
        the filter rules apply to the column index given.
        :param col: signed int
        :return:
        """
        if col <= -1:
            self.countAllColumns = True
            return

        self.countAllColumns = False
        self._sortingColumn = col
        super(CustomSortModel, self).setFilterKeyColumn(col)

编辑:当我试图删除这个问题时,我收到了一个wierd错误,但是我添加了一个更新的错误,并在这里添加了一个更好的简化示例,用于测试:

https://stackoverflow.com/questions/34074825/pyside-qtableview-not-displaying-text-like-pyqt-does

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-04 10:28:29

在PySide中运行代码会产生一系列错误:

AttributeError:“模块”对象没有属性“QVariant”

那是因为有不再使用QVariant中的PySide。用常规python类型替换所有QVariant修复了代码。

例如

代码语言:javascript
运行
复制
return QtCore.QVariant('No Data')

变成了

代码语言:javascript
运行
复制
return "No Data"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34056812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档