2 years ago
#57200

Tuhin Mitra
How to display QTableView Cell background image along with QTableView stylesheet
I want to set stylesheet for QTableView that shows round border along with background image for each cell. This works fine with the following stylesheet:
QTableView{
gridline-color: rgba(0,0,0,0);
}
QTableView::item{
color: white;
background-image: url(cell_bg.png); /*cell bg image*/
padding-left: 5px; /*cell spacing*/
border: 2px solid transparent; /*transparent cell borders*/
border-radius: 10px;
}
But, in the QAbstractTableModel
for the TableView I am using Qt.BackgroundColorRole
to set cell colors based on some logic. When I use the above stylesheet, custom cell colors are not shown.
QTableView without background-image
stylesheet property looks like this:
QTableView with the stylesheet looks like this:
Is there anyway I can set cell background image using stylesheet and also showing Qt.BackgroundColorRole
colors based on my logic?
[Edit] Added this minimal code sample:
import string
import numpy as np
import random
import typing
import pandas as pd
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import Qt
letters = list(string.ascii_uppercase + string.digits)
class SimpleDelegate(QtWidgets.QStyledItemDelegate):
def paint(self, painter: QtGui.QPainter, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> None:
painter.save()
painter.drawPixmap(option.rect.topLeft(), QtGui.QPixmap("cell_bg.png"))
painter.restore()
class MyModel(QtCore.QAbstractTableModel):
def __init__(self, table_data, header_labels):
super(MyModel, self).__init__()
self._data: 'pd.DataFrame' = table_data
self.header_labels = header_labels
self.num_c_bg_props = {'h': 240, 's': 170} # blue for high values
def populate(self, df):
"""Reset the model"""
self.beginResetModel()
self._data = df.copy()
self.endResetModel()
def data(self, index: QtCore.QModelIndex, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole:
return str(self._data.iat[index.row(), index.column()])
elif role == Qt.BackgroundColorRole:
if self.header_labels[index.column()] == "Name":
return QtGui.QColor(0, 255, 110) # black
text = self._data.iat[index.row(), index.column()]
max_col_value = self._data.iloc[:, index.column():index.column() + 1].max()
min_col_value = self._data.iloc[:, index.column():index.column() + 1].min()
intensity_ratio = np.divide(np.subtract(float(text), min_col_value),
np.subtract(max_col_value, min_col_value))
hsv_value = intensity_ratio * 255
hsv_c_tuple = (self.num_c_bg_props['h'], self.num_c_bg_props['s'], int(hsv_value))
return QtGui.QColor.fromHsv(*hsv_c_tuple)
elif role == Qt.ForegroundRole:
if self.header_labels[index.column()] == "Name":
return QtGui.QColor(0, 0, 0) # black
else:
return QtGui.QColor(255, 255, 255) # white
def rowCount(self, parent: QtCore.QModelIndex = ...) -> int:
return len(self._data)
def columnCount(self, parent: QtCore.QModelIndex = ...) -> int:
return len(self.header_labels)
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self.header_labels[section]).upper()
if orientation == Qt.Vertical:
return str(section)
class MyTableView(QtWidgets.QTableView):
def __init__(self):
super(MyTableView, self).__init__()
header_labels = ("Name", "Col1", "Col2", "Col3")
df = pd.DataFrame(columns=header_labels)
for i in range(10):
random.shuffle(letters)
_row = [''.join(letters[:5])]
for _ in range(3):
_row.append(random.random())
df = df.append(dict(zip(header_labels, _row)), ignore_index=True)
self._model = MyModel(df, header_labels)
self.setModel(self._model)
self.setItemDelegateForColumn(0, SimpleDelegate())
fit_to_view_shortcut = QtWidgets.QShortcut("Ctrl+R", self)
fit_to_view_shortcut.activated.connect(self.fit_to_view)
def fit_to_view(self):
tot_size = self.visibleRegion().boundingRect().width()
per_col_width = tot_size // 4
for _ in range(4):
self.setColumnWidth(_, per_col_width)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
tableView_1 = MyTableView()
self.setCentralWidget(tableView_1)
# ::item -> background-image property replace all colors set by code logic
tableView_1.setStyleSheet(
"""
QHeaderView{
background-color: transparent; /* header background*/
color: white;
}
QTableView{
gridline-color: rgba(0,0,0,0);
}
QTableView::item{
color: white;
/*background-image: url(cell_bg.png); /*cell bg image*/*/
padding-left: 5px; /*cell spacing*/
border: 2px solid transparent; /*transparent cell borders*/
border-radius: 10px;
}
QHeaderView::section {
color: white;
background-color: #343434;
font-size: 10pt;
padding: 2px;
border: 1px solid #4a4a4a;
margin: 2px;
}""")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
python
pyqt5
qtableview
qtstylesheets
0 Answers
Your Answer