python - 更改值后使用代理模型更改 QTableView 的单元格的背景颜色
问题描述
我有一个子类QAbstractTableModel
其中包含 None 类型值以将行显示为空
class ViewModel(qtc.QAbstractTableModel):
def __init__(self, input_data=None):
super().__init__()
self.input_data = input_data or [[None, None],[None, None]]
如果插入的值(替换无类型值)在/超出某个范围,我想更改单元格的颜色
像z = 12 <= x <= 20
# False == red, True == green
self.model.layoutChanged.emit()
仅当项目被编辑或被执行时,颜色才会改变
更改 QTableView 的单元格背景颜色的答案建议更改数据方法如何更改 QTableView 的单元格背景颜色 [重复] 但这将在开始时为单元格着色
我在 QT 论坛中找到了一种在视图和模型之间插入代理模型的方法 如何简单地更改 TableView 内单元格的背景颜色
我正在尝试将代码实现到 Pyqt5 中,到目前为止没有成功。是否有我不知道的 PyQt5 方法?
示例代码
import sys
import re
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
class ViewModel(qtc.QAbstractTableModel):
def __init__(self, input_data=None):
super().__init__()
self.input_data = input_data or [[None, None],[None, None]]
def data(self, index, role): # parameter index, role are needed !
if role == qtc.Qt.DisplayRole:
try:
text = self.input_data[index.row()][index.column()]
except IndexError:
text = None
return text
def rowCount(self, index=qtc.QModelIndex()):
return 0 if index.isValid() else len(self.input_data)
def columnCount(self, index):
return len(self.input_data[0])
def headerData(self, section, orientation, role):
# section is which index of the orientation
if role == qtc.Qt.DisplayRole:
if orientation == qtc.Qt.Vertical:
return "row"
def flags(self, index):
return qtc.Qt.ItemIsEditable | qtc.Qt.ItemIsSelectable | qtc.Qt.ItemIsEnabled
def setData(self, index, value, role=qtc.Qt.EditRole):
if role == qtc.Qt.EditRole:
try:
row = index.row()
column = index.column()
pattern = '^[\d]+(?:,[\d]+)?$'
if re.fullmatch(pattern, value, flags=0):
print("true")
self.input_data[row][column] = value # float
else:
print("nope")
pass
return True
except ValueError:
print("not a number")
return False
class MainWindow(qtw.QWidget):
def __init__(self):
super().__init__()
# View
table_view = qtw.QTableView()
self.model = ViewModel()
table_view.setModel(self.model)
# size and position
qtRectangle = self.frameGeometry()
centerPoint = qtw.QDesktopWidget().availableGeometry().center()
qtRectangle.moveCenter(centerPoint)
self.move(qtRectangle.topLeft())
# size
self.resize(1000, 410)
# layout
qvboxlayout = qtw.QVBoxLayout()
qvboxlayout.addWidget(table_view)
self.setLayout(qvboxlayout)
self.show()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = MainWindow()
sys.exit(app.exec_())
解决方案
如果你想使用代理来改变颜色,那么只有data()
方法应该被覆盖:
class ColorProxy(qtc.QIdentityProxyModel):
def data(self, index, role=qtc.Qt.DisplayRole):
if role == qtc.Qt.BackgroundRole:
data = index.data()
try:
value = float(data)
except (ValueError, TypeError) as e:
print("error:", e)
else:
return qtg.QColor("green") if 12 <= value <= 20 else qtg.QColor("red")
return super().data(index, role)
# ...
self.model = ViewModel()
proxy = ColorProxy()
proxy.setSourceModel(self.model)
table_view.setModel(proxy)
# ...
另一种解决方案是使用委托
class ColorDelegate(qtw.QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
data = index.data()
try:
value = float(data)
except (ValueError, TypeError) as e:
print("error:", e)
else:
color = qtg.QColor("green") if 12 <= value <= 20 else qtg.QColor("red")
option.backgroundBrush = color
# ...
table_view = qtw.QTableView()
self.model = ViewModel()
delegate = ColorDelegate(table_view)
table_view.setItemDelegate(delegate)
table_view.setModel(self.model)
# ...
推荐阅读
- php - 动态产品页面和 SQL 注入漏洞
- java - 我想使用 Fluent 等待返回 void,该怎么做?
- r - 如何通过R中的样本ID创建样本类型值差异的数据框?
- r - 如果没有超过一定数量的值,则从 tibble 过滤/删除行
- makefile - -emit-llvm 链接时不能使用
- java - 为什么在执行 poll() 时优先队列重新排序元素?
- python - 使用定义函数将华氏度转换为摄氏度的程序
- r - 在 R 中运行此 for/if 代码时出现“缺失值”错误
- javascript - 解构函数参数的 TS 语法
- javascript - 如何为表单提交按钮创建一个“onClick”事件,该按钮将数据发布到 Netlify 并重定向到 Stripe Checkout?