如何在QTableView行上实现悬停效果

问题描述 投票:0回答:1

import sys
from PySide2.QtGui import QColor, QBrush
from PySide2.QtWidgets import QStyledItemDelegate, QApplication, QTableView, QAbstractItemView, QStyle
from PySide2.QtCore import Qt, QModelIndex, QAbstractTableModel, QEvent



class TBV(QTableView):
    def __init__(self) -> None:
        super().__init__()
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setMouseTracking(True)


class DEG(QStyledItemDelegate):
    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        self.currentHoveredRow = -1

    def paint(self, painter, option, index: QModelIndex) -> None:
        if option.state & QStyle.State_MouseOver:
            if self.currentHoveredRow == index.row():
                option.backgroundBrush = QBrush(QColor(Qt.red))
                # option.palette.setBrush(option.palette.Base, QBrush(QColor(Qt.red)))

        return super().paint(painter, option, index)
    
    def editorEvent(self, event, model, option, index: QModelIndex) -> bool:
        if event.type() == QEvent.MouseMove:
            if index.row() != self.currentHoveredRow:
                self.currentHoveredRow = index.row()
                self.parent().viewport().update()

        return super().editorEvent(event, model, option, index)



class MDL(QAbstractTableModel):
    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        self._tabledata = [['mike', 12], ['kk', 13], ['jane', 14]]

    def rowCount(self, parent: QModelIndex = ...) -> int:
        return len(self._tabledata)

    def columnCount(self, parent: QModelIndex = ...) -> int:
        return len(self._tabledata[0] if self._tabledata else [])

    def data(self, index: QModelIndex, role: int = ...):
        if not index.isValid():
            return None
        if 0 == self.rowCount():
            return None
        if index.row() >= self.rowCount():
            return None
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self._tabledata[index.row()][index.column()]

        else:
            return None

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = TBV()
    demo.setItemDelegate(DEG(demo))
    model = MDL(demo)
    demo.setModel(model)
    demo.show()
    sys.exit(app.exec_())

如标题所述,我需要在悬停的行上设置悬停效果。 我想这样的视觉效果不能只通过QSS来设置。 因此,如何在 python 代码中做到这一点。

我上面提供的代码,

editorEvent
方法将接收MouseMove事件并获取悬停的行索引,稍后
update
方法将触发
paint
方法,但是,

option.backgroundBrush = QBrush(QColor(Qt.red))
# option.palette.setBrush(option.palette.Base, QBrush(QColor(Qt.red)))

这些代码不会更改悬停行的背景颜色。 我不知道怎么办。

python-3.x qt pyqt pyqt5 pyside2
1个回答
0
投票

设置选项的

backgroundBrush
是无效的,因为
paint()
会创建选项的副本并使用
initStyleOption()
进行初始化。

您可以做的是覆盖

initStyleOption()
,然后设置背景以防万一:

  • state
    State_MouseOver
    (正如您已经所做的那样);
  • 同一行中的任何其他“兄弟”可能包含鼠标光标;
class DEG(QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)

        model = index.model()
        col = index.column()
        view = self.parent()

        if option.state & QStyle.State_MouseOver:
            option.backgroundBrush = QBrush(Qt.red)
        else:
            pos = view.viewport().mapFromGlobal(QCursor.pos())
            for c in range(model.columnCount()):
                if c != col:
                    r = view.visualRect(index.siblingAtColumn(c))
                    if r.adjusted(0, 0, 1, 1).contains(pos):
                        option.backgroundBrush = QBrush(Qt.red)

请注意,不必覆盖

editorEvent()
,但是,即使是这样,您也应该在
any
情况下调用 update(),即使移动不是之前悬停的行单元格。

在任何情况下,您都不能单独使用

editorEvent()
进行更新,因为它跟踪leave事件,这意味着如果鼠标将行留在视图的空白区域,则不会更新行。

© www.soinside.com 2019 - 2024. All rights reserved.