Skip to main content
 首页 » 编程设计

python之QTableView 上的 PySide 委托(delegate),带有文本和勾号

2025年05月04日9虾米哥

我正在使用自定义模型实现 QTableView,我需要一个如下所示的单元格:

目前我使用下面的委托(delegate)(改编自其他答案)在单个单元格上绘制一个标志(html 彩色文本),单击整个单元格会更改标志。

class HTMLDelegate(QtGui.QStyledItemDelegate): 
    def Doc(self, options): 
        if options.text == "0": 
            return "" 
        elif options.text == "1": 
            return "<b><font align='right' color='green'>V</font></b>" 
        elif options.text == "2": 
            return "<font align='right' color='#FF8400'>!!</font>" 
        elif options.text == "3": 
            return "<b><font align='right' color='#CC0000'>F</font></b>" 
        elif options.text == "4": 
            return "<b><font align='right' color='#000000'>X</font></b>" 
 
    def paint(self, painter, option, index): 
        options = QtGui.QStyleOptionViewItemV4(option) 
        self.initStyleOption(options,index) 
 
        style = QtGui.QApplication.style() if options.widget is None else options.widget.style() 
 
        doc = QtGui.QTextDocument() 
 
        background = None 
        doc.setHtml(self.Doc(options)) 
 
        options.text = "" 
        style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter); 
 
        ctx = QtGui.QAbstractTextDocumentLayout.PaintContext() 
 
        # Highlighting text if item is selected 
        #if (optionV4.state & QStyle::State_Selected) 
        #    ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText)); 
 
        textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, options, None) 
        painter.save() 
        if background: 
            painter.fillRect(options.rect, QtCore.Qt.yellow) 
        painter.translate(textRect.topLeft()) 
        painter.setClipRect(textRect.translated(-textRect.topLeft())) 
 
        doc.documentLayout().draw(painter, ctx) 
 
        painter.restore() 
 
    def editorEvent(self, event, model, option, index): 
        if not (index.flags() & QtCore.Qt.ItemIsEditable) > 0: 
            return False 
 
        # Do not change the checkbox-state 
        if event.type() == QtCore.QEvent.MouseButtonRelease or event.type() == QtCore.QEvent.MouseButtonDblClick: 
            if event.button() != QtCore.Qt.LeftButton: 
                return False 
            if event.type() == QtCore.QEvent.MouseButtonDblClick: 
                return True 
        elif event.type() == QtCore.QEvent.KeyPress: 
            if event.key() != QtCore.Qt.Key_Space and event.key() != QtCore.Qt.Key_Select: 
                return False 
        else: 
            return False 
                          
        # Change the flag-state 
        self.setModelData(None, model, index) 
        return False 
 
 
    def setModelData (self, editor, model, index): 
        ''' 
        The user wanted to change the old flag into the next 
        ''' 
        #newValue = not bool(index.model().data(index, QtCore.Qt.DisplayRole)) 
        #model.setData(index, newValue, QtCore.Qt.EditRole) 
        oldFlagIndex = model.index(index.row(), COD_COL_FLAGS) 
        oldFlag = model.data(oldFlagIndex) 
 
        if type(oldFlag) == long: 
            newFlag = oldFlag + 1 
            if newFlag > 4: 
                newFlag = 0 
        else: 
            newFlag = 0 
        model.setData(index, newFlag, QtCore.Qt.EditRole) 

我怎样才能做到这一点?
我想到的选项是:

  • 在右侧绘制文本(丰富或简单)以及像素图的委托(delegate)

  • 绘制两个文本字符串(一个普通文本和一个富文本,或者都是富文本)的委托(delegate),一个左对齐,一个右对齐

作为练习,但应用程序不需要,如果仅在单击标志而不是整个单元格时触发标志更改会很好。

谢谢

请您参考如下方法:

paint 事件有一个名为 option 的参数,它应该包含一个 rect 对象。该矩形对象是绘制内容的边界。您应该能够更改该矩形的宽度,并为您想要绘制第二部分的位置创建一个新矩形。

rect = options.rect 
options.rect = QtCore.QRect(rect.x(), rect.y(), rect.width()/2, rect.height()) 
style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter); 
options.rect = QtCore.QRect(rect.x()+rect.width()/2, rect.y(), rect.width()/2, rect.height()) 
options.text = "right side" 
style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter);