You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt6:QTableView选中高亮自定义失效问题求助

问题

想自定义QTableView选中项的高亮区域,但将QListView中可用的代码迁移过来后,出现自定义高亮与默认高亮同时显示的异常情况。

QListView 可行示例代码

from PySide6 import QtCore as qtc
from PySide6 import QtGui as qtg
from PySide6 import QtWidgets as qtw

class ListItemsDelegate(qtw.QStyledItemDelegate):
    def paint(self, painter: qtg.QPainter, option: qtw.QStyleOptionViewItem, index: qtc.QModelIndex) -> None:
        if option.state & qtw.QStyle.StateFlag.State_Selected:
            painter.fillRect(
                    qtc.QRect(
                        option.rect.left(),
                        option.rect.top(),
                        20,
                        option.rect.height()
                    ),
                    qtc.Qt.GlobalColor.blue,
            )
        option.state &= ~qtw.QStyle.StateFlag.State_Selected
        option.state &= ~qtw.QStyle.StateFlag.State_HasFocus
        painter.drawText(option.rect.topLeft(), "text")

app = qtw.QApplication()

model = qtc.QStringListModel([1, 2, 3])
view = qtw.QListView()
view.setModel(model)
view.setItemDelegate(ListItemsDelegate())
view.show()

app.exec()

效果:仅显示左侧20px宽度的蓝色高亮,无默认选中背景。

QTableView 异常示例代码

from PySide6 import QtCore as qtc
from PySide6 import QtGui as qtg
from PySide6 import QtWidgets as qtw

class TableItemsDelegate(qtw.QStyledItemDelegate):
    def paint(self, painter: qtg.QPainter, option: qtw.QStyleOptionViewItem, index: qtc.QModelIndex) -> None:
        if option.state & qtw.QStyle.StateFlag.State_Selected:
            highlight_rect = qtc.QRect(option.rect)
            highlight_rect.adjust(20, 20, -20, -20)
            painter.fillRect(
                    highlight_rect,
                    qtc.Qt.GlobalColor.blue,
            )
        option.state &= ~qtw.QStyle.StateFlag.State_Selected
        option.state &= ~qtw.QStyle.StateFlag.State_HasFocus
        painter.drawText(option.rect.topLeft(), "text")

class TableModel(qtc.QAbstractTableModel):
    def data(self, *args) -> int:
        return 1

    def rowCount(self, *args) -> int:
        return 5

    def columnCount(self, *args) -> int:
        return 5

app = qtw.QApplication()

view = qtw.QTableView()
view.setModel(TableModel())
view.setItemDelegate(TableItemsDelegate())
view.show()

app.exec()

效果:自定义的缩小版蓝色高亮与默认的全单元格灰色高亮同时显示。

问题原因

  • QListView的默认选中背景由ItemDelegate负责绘制,所以在Delegate中清除State_Selected状态后,默认高亮不会被绘制;
  • QTableView的默认选中背景由视图本身(QTableView)绘制,而非ItemDelegate。即便在Delegate中清除了选中状态,视图仍会自行绘制默认选中高亮,导致两个高亮叠加。

解决方法

方案1:禁用QTableView默认选中背景(推荐)

在创建QTableView后添加样式表代码,让视图不再绘制默认选中背景:

view.setStyleSheet("QTableView::item:selected { background: transparent; }")

方案2:重写QTableView的paintEvent(灵活但繁琐)

如果需要更复杂的绘制控制,可以重写QTableView的paintEvent方法,跳过默认选中背景的绘制逻辑,但这种方式代码量更大,一般优先选择方案1。


内容的提问来源于stack exchange,提问作者Neat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:25:51