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)))
这些代码不会更改悬停行的背景颜色。 我不知道怎么办。
设置选项的
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事件,这意味着如果鼠标将行留在视图的空白区域,则不会更新行。