【问题标题】:Unexpected padding pyqt in qtableview cellqtableview 单元格中的意外填充 pyqt
【发布时间】:2018-10-23 06:08:26
【问题描述】:

我正在尝试为QTableView 创建一个自定义TableModel 类。包含1 作为数据的单元格必须有红色轮廓。大纲是通过从TableModel 返回一个像素图(带有红色边框和顶部绘制的文本)而不是返回一个简单的字符串来进行的。

问题在于像素图的意外填充,我将其返回为DecorationRole。我在return pixmap 行之前检查了像素图是否正确绘制(实际上是21x21 像素,轮廓做得很好,没有填充,正如计划的那样)。

这是正确绘制的像素图,它保存在 TableModel 的 return 之前:

最终,某些东西将返回的像素图从QTableView 单元格的左边框移动了 3px。我没有在 QtDesigner 中为 QTableView 设置任何填充,以后也没有在我的代码中更改它。我还尝试使用样式表手动将填充设置为零,但没有给出不同的结果。

任何想法如何解决它?谢谢。

这是我TableModel的示例:

class TableModel(QtCore.QAbstractTableModel):
def __init__(self, topology=None):
    super().__init__()
    ...
    # Hardcode cell size and path to rectangle image
    self.cell_width, self.cell_height = 21, 21
    self.fpath_red_rect = './path/to/red_rect.png'

def rowCount(self, parent=QtCore.QModelIndex()):
    return self.data.shape[0]

def columnCount(self, parent=QtCore.QModelIndex()):
    return self.data.shape[1]

def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
    ...

def size(self):
    return QtCore.QSize((self.columnCount() + 1) * self.cell_width,
                        (self.rowCount() + 1) * self.cell_height)

def data(self, index, role=QtCore.Qt.DisplayRole):
    if not index.isValid():
        return QtCore.QVariant()

    i = index.row()
    j = index.column()

    if role == QtCore.Qt.DisplayRole:
        if self.data[i, j] == 0:      # empty
            return ''
        elif self.data[i, j] == 1:    # cell with red rectangle
            # the text will be drawn on pixmap manually later
            return None
        else:
            return '{0}'.format(self.data[i, j])    # display default data

    if role == QtCore.Qt.DecorationRole:
        # Create pixmap, draw the rectangle on it and then draw text on top
        pixmap = QtGui.QPixmap(self.cell_width, self.cell_height)
        image = QtGui.QImage(self.fpath_red_rect).scaled(self.cell_width, self.cell_height)
        painter = QtGui.QPainter(pixmap)
        painter.drawImage(pixmap.rect().topLeft(), image)
        painter.drawText(pixmap.rect(), QtCore.Qt.AlignCenter, '{0}'.format(self.data[i, j]))
        painter.end()

        # If we save the pixmap to PNG image here (see the link above),
        # we get the expected 21 x 21 px image, with nice
        # and properly drawn rectangle and centered text.
        # But something goes wrong after returning

        return pixmap

    if role == QtCore.Qt.BackgroundRole:
        return QtGui.QBrush(self.getQtColor(self.data[i, j]))

    if role == QtCore.Qt.TextAlignmentRole:
        return QtCore.Qt.AlignCenter

    return QtCore.QVariant()

【问题讨论】:

    标签: python python-3.x pyqt qtableview qabstracttablemodel


    【解决方案1】:

    DecorationRole 用于绘制图标,因此您观察位移,在您的情况下,您不应该使用该角色,此外不应在模型中完成绘画任务,因为他只需要提供数据,如果您想修改绘图,更好的选择是使用如下所示的委托:

    import sys
    
    import numpy as np
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    ValueRole = QtCore.Qt.UserRole + 1
    max_val = 4
    
    colors = [QtGui.QColor(*np.random.randint(255, size=3)) for i in range(max_val)]
    
    
    class TableModel(QtCore.QAbstractTableModel):
        def __init__(self, parent=None):
            QtCore.QAbstractTableModel.__init__(self, parent)
            self.data = np.random.randint(max_val, size=(10, 10))
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            return self.data.shape[0]
    
        def columnCount(self, parent=QtCore.QModelIndex()):
            return self.data.shape[1]
    
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if not index.isValid():
                return QtCore.QVariant()
    
            i = index.row()
            j = index.column()
            val = self.data[i, j]
    
            if role == QtCore.Qt.DisplayRole:
                return str(val)
    
            elif role == QtCore.Qt.TextAlignmentRole:
                return QtCore.Qt.AlignCenter
    
            elif role == QtCore.Qt.BackgroundRole:
                return colors[val]
    
            if role == ValueRole:
                return val
    
            return QtCore.QVariant()
    
    class Delegate(QtWidgets.QStyledItemDelegate):
        def paint(self, painter, option, index):
            QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)
            if index.data(ValueRole) == 1:
                painter.save()
                pen = painter.pen()
                pen.setColor(QtCore.Qt.red)
                painter.setPen(pen)
                r = QtCore.QRect(option.rect)
                r.adjust(0, 0, -pen.width(), -pen.width())
                painter.drawRect(r)
                painter.restore()
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        w = QtWidgets.QTableView()
        w.setItemDelegate(Delegate(w))
        model = TableModel()
        w.setModel(model)
    
        w.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)
        w.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)
    
        for i in range(model.rowCount()):
            w.verticalHeader().resizeSection(i, 21)
    
        for j in range(model.columnCount()):
            w.horizontalHeader().resizeSection(j, 21)
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 非常感谢!我被这个问题困扰了很长时间。您与代表的解决方案解决了问题。现在一切正常。
    猜你喜欢
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 2019-09-08
    • 2014-01-22
    • 1970-01-01
    相关资源
    最近更新 更多