Можно ли условно изменить цвет фона элементов в QTableView, используя PySide2?Я много читал о фреймворке модели .Я не могу понять, нужно ли использовать делегата или нет.Недавно я смог получить столбец флажков без делегата.Я считаю, что виртуальные методы setItemData(index, roles)
и itemData(index)
могут быть тем, что мне нужно.Однако в PySide2 нет QMap
.Моя модель должна где-то хранить дополнительную информацию, которая будет использоваться QtCore.Qt.BackgroundRole
(это перечисление, кстати, говорит «фоновая кисть, используемая для элементов, отображаемых с делегатом по умолчанию») Если я не указываю делегата, это «делегат по умолчанию "используется?"Должен ли я использовать QStandardItemModel
вместо этого?В приведенном ниже примере кода, как я могу получить красный цвет фона определенного столбца на основе некоторых порогов (минимальные и максимальные столбцы являются пороговыми значениями?
from PySide2.QtWidgets import (QWidget, QApplication, QTableView,QVBoxLayout)
import sys
from PandasModel2 import PandasModel2
import numpy as np
import pandas as pd
class Example(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(300, 300, 700, 300)
self.setWindowTitle("QTableView")
self.initData()
self.initUI()
def initData(self):
data = pd.DataFrame(np.random.randint(1,10,size=(6,4)), columns=['Test#','MIN', 'MAX','MEASURED'])
data['Test#'] = [1,2,3,4,5,6]
#add the checkable column to the DataFrame
data['Check'] = True
self.model = PandasModel2(data)
def initUI(self):
self.tv = QTableView(self)
self.tv.setModel(self.model)
vbox = QVBoxLayout()
vbox.addWidget(self.tv)
self.setLayout(vbox)
app = QApplication([])
ex = Example()
ex.show()
sys.exit(app.exec_())
И у меня есть пользовательская модель, использующая пандфрейм данных:
import PySide2.QtCore as QtCore
class PandasModel2(QtCore.QAbstractTableModel):
"""
Class to populate a table view with a pandas dataframe.
This model is non-hierachical.
"""
def __init__(self, data, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self._data = data
def rowCount(self, parent=None):
return self._data.shape[0]
def columnCount(self, parent=None):
return self._data.shape[1]
def data(self, index, role=QtCore.Qt.DisplayRole):
if role==QtCore.Qt.DisplayRole:
if index.column() != 4:
#don't want what determines check state to be shown as a string
if index.isValid():
if index.column() in [1,2,3]:
return '{:.3f}'.format(self._data.iloc[index.row(), index.column()])
if index.column() == 0:
return '{:.2f}'.format(self._data.iloc[index.row(), index.column()])
return str(self._data.iloc[index.row(), index.column()])
if role==QtCore.Qt.CheckStateRole:
if index.column()==4:#had to add this check to get the check boxes only in column 10
if self._data.iloc[index.row(), index.column()] == True:
return QtCore.Qt.Checked
else:
return QtCore.Qt.Unchecked
def getMinimum(self, row):
return self._data.iloc[row, self.getColumnNumber('MIN')]
def getMaximum(self, row):
return self._data.iloc[row, self.getColumnNumber('MAX')]
def getColumnNumber(self, string):
'''
Given a string that identifies a label/column,
return the location of that label/column.
This enables the config file columns to be moved around.
'''
return self._data.columns.get_loc(string)
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self._data.columns[col]
return None
def flags(self, index):
'''
The returned enums indicate which columns are editable, selectable,
checkable, etc.
The index is a QModelIndex.
'''
if index.column() == self.getColumnNumber('Check'):
#print(index.column())
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsUserCheckable
else:
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable
return QtCore.Qt.ItemIsEnabled
def setData(self, index, value, role=QtCore.Qt.DisplayRole):
"""Set the value to the index position depending on Qt::ItemDataRole and data type of the column
Args:
index (QtCore.QModelIndex): Index to define column and row.
value (object): new value.
role (Qt::ItemDataRole): Use this role to specify what you want to do.
Raises:
TypeError: If the value could not be converted to a known datatype.
Returns:
True if value is changed. Calls layoutChanged after update.
False if value is not different from original value.
"""
if not index.isValid():
return False
if role == QtCore.Qt.DisplayRole: #why not edit role?
self._data.iat[index.row(),index.column()]= value
self.layoutChanged.emit()
return True
elif role == (QtCore.Qt.CheckStateRole | QtCore.Qt.DisplayRole):
#this block does get executed when toggling the check boxes,
#verified with debugger. Although the action is the same
#as the block above!
self._data.iat[index.row(),index.column()]= value
self.layoutChanged.emit()
return True
else:
return False