QTableWidget ItemDelegate中断选择

2024-09-29 21:26:37 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面的python2.7、PyQt4示例中,我生成了2个QTableWidgets。表1没有ItemDelegate,表2有HTMLDelegate。你知道吗

如果表格具有焦点,则选定的背景色起作用,但当表格失去焦点时,蓝色选择在table2上变为灰色。当焦点丢失时,我希望table2选择像table1一样工作。你知道吗

使用itemdegate时,如何保持蓝色选择外观而不考虑焦点?你知道吗

enter image description here

import sip
sip.setapi('QVariant', 2)   

from PyQt4 import QtCore, QtGui
import random

from html import escape

words = [
    "Hello",
    "world",
    "Stack",
    "Overflow",
    "Hello world",
]

class HTMLDelegate(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None):
        super(HTMLDelegate, self).__init__(parent)
        self.doc = QtGui.QTextDocument(self)

    def paint(self, painter, option, index):

        col = index.column()
        row = index.row()

        painter.save()

        options = QtGui.QStyleOptionViewItem(option)
        self.initStyleOption(options, index)

        text = index.data()

        self.doc.setHtml(text)

        options.text = ""
        style = (
            QtGui.QApplication.style()
        )
        style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter)

        ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()

        if option.state & QtGui.QStyle.State_Selected:
            ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText), )
        else:
            ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(QtGui.QPalette.Active, QtGui.QPalette.Text), )

        textRect = (options.rect)  

        constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - constant
        textRect.setTop(textRect.top() + margin)

        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()

    def sizeHint(self, option, index):
        return QSize(self.doc.idealWidth(), self.doc.size().height())


class Widget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        hlay = QtGui.QHBoxLayout()
        lay = QtGui.QVBoxLayout(self)

        self.table1 = QtGui.QTableWidget(4, 2)
        self.table2 = QtGui.QTableWidget(4, 2)
        lay.addLayout(hlay)
        lay.addWidget(self.table1)
        lay.addWidget(self.table2)

        # define itemdelegate for table1, but not for table2
        self.table2.setItemDelegate(HTMLDelegate(self.table2))

        # fill table1
        for i in range(self.table1.rowCount()):
            for j in range(self.table1.columnCount()):
                it = QtGui.QTableWidgetItem(random.choice(words))
                self.table1.setItem(i, j, it)

        # fill table2
        for i in range(self.table2.rowCount()):
            for j in range(self.table2.columnCount()):
                it = QtGui.QTableWidgetItem(random.choice(words))
                self.table2.setItem(i, j, it)        

if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)

    app.setStyle("Plastique")   # set style

    stylesheet = """
    QPushButton:hover, QComboBox:hover
    {
        background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #cbc9c5, stop: 1 #b9b7b5);
        border: 2px solid #78879b;
        border-radius: 3px;
    }
    QTableWidget::item:selected 
    {
        background: #0078d7;  
        color: white;
    }
    QTableWidget
    {
        font: 9pt "Segoe UI"; 
    }
    QHeaderView
    {
        font: 9pt "Segoe UI"; 
    }
    """    

    app.setStyleSheet(stylesheet)       

    myapp = Widget()     
    myapp.show()           

    rc = app.exec_()

    myapp.close()

    sys.exit(rc)    

Tags: importselfforindexdoc焦点optionsoption
1条回答
网友
1楼 · 发布于 2024-09-29 21:26:37

您正在使用QStyleOptionViewItem,它在Qt4中是一个非常基本的类,而您需要的是^{},它实现了许多有用的东西,包括装饰(如在item icon中)及其位置、根据其他项的项位置,最重要的是,委托所使用的小部件及其完整的QStyle绘制功能。你知道吗

style.drawControl方法和大多数QStyle方法一样,也有一个widget参数;它通常被忽略,但在这种情况下非常重要,特别是在有样式表的情况下。你知道吗

我建议您使用option方法的paint()类作为参考来创建您自己的选项,该选项将自动使用ViewItem可用的最新QStyleOption,并且还将使将来可能更容易过渡到Qt5。你知道吗

请记住,根据文档(这一点有点模糊),widget属性只能从QStyleOptionViewItem的版本3获得,但是根据我的测试,正确的背景绘制无论如何都会失败。如果出于任何原因,您一直使用Qt的一个非常的旧版本,它不提供QStyleOptionViewItemV4,恐怕您唯一的选择就是将背景色引用保留在某个地方(无法从代码中访问样式表颜色,它与QTableView Highlight调色板角色不匹配,并且自己手动绘制背景。你知道吗

    def paint(self, painter, option, index):
        #...
        newOption = option.__class__(option)
        self.initStyleOption(newOption, index)
        #...
        style = newOption.widget.style() if newOption.widget else QtGui.QApplication.style()
        style.drawControl(QtGui.QStyle.CE_ItemViewItem, newOption, painter, newOption.widget)
        # ...

PS:我建议您不要对对象使用太相似的名称:我实际上找不到问题的根源,因为我经常混淆“option”和“options”:这就是我更改它的原因,这对于可读性和调试目的来说也更好。你知道吗

相关问题 更多 >

    热门问题