![](/img/trans.png)
[英]How to change background color of selected or clicked cell in a pyqt5 QTableWidget?
[英]Background color of the particular cell is not changing after clicking specific cells in qTableWidget pyqt5
所以我有一个 1 行多列的表格,我使用自定义委托 function 作为图像缩略图。 当我单击它时,我还包括了设置的背景颜色 function。 但是,它不会更改项目背景的颜色。 我必须使用自定义委托 function 以便我的图标图像从不同的单元格相互粘贴,而没有任何额外的空格。
我的代码如下
import random
from PyQt5 import QtCore, QtGui, QtWidgets
imagePath2 = "arrowREDHead.png"
imagePath = "arrowREDBody.png"
class IconDelegate(QtWidgets.QStyledItemDelegate):
def paint(self, painter, option, index):
icon = index.data(QtCore.Qt.DecorationRole)
mode = QtGui.QIcon.Normal
if not (option.state & QtWidgets.QStyle.State_Enabled):
mode = QtGui.QIcon.Disabled
elif option.state & QtWidgets.QStyle.State_Selected:
mode = QtGui.QIcon.Selected
state = (
QtGui.QIcon.On
if option.state & QtWidgets.QStyle.State_Open
else QtGui.QIcon.Off
)
pixmap = icon.pixmap(option.rect.size(), mode, state)
painter.drawPixmap(option.rect, pixmap)
def sizeHint(self, option, index):
return QtCore.QSize(20, 20)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
table = QtWidgets.QTableWidget(1, 10)
delegate = IconDelegate(table)
table.setItemDelegate(delegate)
self.setCentralWidget(table)
for j in range(table.columnCount()):
if(j % 2 == 0):
pixmap = QtGui.QPixmap(imagePath)
icon = QtGui.QIcon(pixmap)
it = QtWidgets.QTableWidgetItem()
it.setIcon(icon)
table.setItem(0, j, it)
else:
pixmap = QtGui.QPixmap(imagePath2)
icon = QtGui.QIcon(pixmap)
it = QtWidgets.QTableWidgetItem()
it.setIcon(icon)
table.setItem(0, j, it)
table.item(0, 1).setBackground(QtGui.QColor(100,100,150))
table.resizeRowsToContents()
table.resizeColumnsToContents()
table.setShowGrid(False)
table.itemClicked.connect(self.sequenceClicked)
def sequenceClicked(self, item):
self.itemClicked = item
print("item", item)
item.setBackground(QtGui.QColor(255, 215, 0))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
这是图标之间有间隙的图像,它形成的不是一个完美的箭头,这就是为什么我使用自定义委托 function 将图标粘在一起,让它看起来像一个完美的箭头
这是具有完美箭头外观的图像,因为使用委托 function 在单元格之间没有任何间隙。 但是,它不允许我更改单元格的背景颜色。
这是箭头的图像
这是箭头体的图像
与任何重写的 function 一样,如果未调用基本实现,则忽略默认行为。
paint()
是 function 负责绘制项目的任何方面,包括其背景。 由于在您的覆盖中您只是在绘制像素图,因此缺少其他所有内容,因此解决方案是调用基本实现然后绘制像素图。
但是,在这种特定情况下,这不是正确的选择,因为基本实现已经绘制了项目的装饰,并且在某些条件下(假设像素图具有 alpha 通道),它可能会导致图像重叠.
有三种可能的解决方案。
在这种情况下,我们执行基本实现的操作,即使用 CE_ItemViewItem 调用样式drawControl
CE_ItemViewItem
,但我们在此之前修改选项,删除与图标相关的任何内容:
def paint(self, painter, option, index):
# create a new option (as the existing one should not be modified)
# and initialize it for the current index
option = QtWidgets.QStyleOptionViewItem(option)
self.initStyleOption(option, index)
# remove anything related to the icon
option.features &= ~option.HasDecoration
option.decorationSize = QtCore.QSize()
option.icon = QtGui.QIcon()
if option.widget:
style = option.widget.style()
else:
style = QtWidgets.QApplication.style()
# call the drawing function for view items
style.drawControl(style.CE_ItemViewItem, option, painter, option.widget)
# proceed with the custom drawing of the pixmap
icon = index.data(QtCore.Qt.DecorationRole)
# ...
QStyledItemDelegate 总是在其大多数函数的开头调用initStyleOption
,包括paint
和sizeHint
。 通过覆盖 function,我们可以更改绘图的某些方面,包括图标 alignment 和定位。
在这种特定情况下,知道我们只有两种类型的图标,并且它们必须根据图像右对齐或左对齐,因此更新适当的装饰尺寸(基于图标的最佳尺寸)就足够了,然后alignment 基于列。
class IconDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
option.decorationSize = option.icon.actualSize(option.rect.size())
if index.column() & 1:
option.decorationPosition = option.Left
option.decorationAlignment = QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
else:
option.decorationPosition = option.Right
option.decorationAlignment = QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
注意:此方法仅适用于图像都具有相同比例且未手动更改行高的情况。
Qt 使用角色来存储和检索每个索引的各个方面(字体、背景等),并且可以定义用户角色来存储自定义数据。
setIcon()
实际上使用DecorationRole
在项目中设置一个QIcon,并且委托使用它来绘制它。 如果为该角色返回的数据为空/无效,则不会绘制任何图标。
如果我们不使用setIcon()
而是将图标存储在具有自定义角色的项目中,默认的绘图函数显然不会绘制任何装饰,但我们仍然可以从委托中访问它。
# we usually define roles right after the imports, as they're constants
ImageRole = QtCore.Qt.UserRole + 1
class IconDelegate(QtWidgets.QStyledItemDelegate):
def paint(self, painter, option, index):
super().paint(painter, option, index)
icon = index.data(ImageRole)
# ...
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
# ...
it = QtWidgets.QTableWidgetItem()
it.setData(ImageRole, pixmap)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.