根据QTableView中的用户输入更改行的颜色

问题描述 投票:0回答:1

我将首先解释我的目标。包含多个产品的电子商务订单将加载到qtableview中。程序的用户将扫描产品的ean代码,如果qtableview中存在ean代码,则该行应将颜色更改为绿色或黄色。如果一个产品的数量大于1,颜色应该变为黄色,直到扫描的产品数量等于订单中的数量,

总体目标是快速简便地确保正确的产品按正确的顺序放置。

我已经找到了很多关于如何永久更改行颜色的答案,但没有找到如何根据用户输入更改颜色以及更改模型中的值的答案。

我想要实现的例子。 enter image description here

python python-3.x pyqt pyqt5 qtableview
1个回答
0
投票

有以下替代方案:

  • QIdentityProxyModel:您必须覆盖数据方法并使用值计算颜色,如果颜色与预设颜色不同,请将背景颜色设置为原始模型。 import sys import random from functools import partial from PyQt5 import QtCore, QtGui, QtWidgets def calculate_color(model, row): max_value = int(model.index(row, 2).data()) current_value = int(model.index(row, 3).data()) if current_value == 0: return QtGui.QBrush(QtCore.Qt.white) elif max_value == current_value: return QtGui.QBrush(QtCore.Qt.green) else: return QtGui.QBrush(QtCore.Qt.yellow) class IdentityProxyModel(QtCore.QIdentityProxyModel): def data(self, index, role=QtCore.Qt.DisplayRole): if role == QtCore.Qt.DisplayRole and index.column() in (2, 3): sm = self.sourceModel() row = index.row() color = calculate_color(sm, row) if color is not None and color != index.data(QtCore.Qt.BackgroundRole): for i in range(sm.columnCount()): sm.setData(sm.index(row, i), color, QtCore.Qt.BackgroundRole) return super(IdentityProxyModel, self).data(index, role) class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.tableView = QtWidgets.QTableView() self.setCentralWidget(self.tableView) self.model = QtGui.QStandardItemModel() self.model.setHorizontalHeaderLabels(["Prod Name", "EAN","Quanyity", "Counted"]) proxy = IdentityProxyModel(self) proxy.setSourceModel(self.model) self.tableView.setModel(proxy) data = [["Prod1", "123456", 0, 0], ["Prod2", "234567", 0, 0], ["Prod3", "345678", 0, 0]] for r, rowData in enumerate(data): for c, d in enumerate(rowData): it = QtGui.QStandardItem(str(d)) self.model.setItem(r, c, it) # launch test for i in range(self.model.rowCount()): self.reset(i) def reset(self, row): max_value = random.randint(1, 10) self.model.item(row, 2).setText(str(max_value)) self.model.item(row, 3).setText("0") QtCore.QTimer.singleShot(1000, partial(self.start_test, row)) def start_test(self, row): max_value = int(self.model.item(row, 2).text()) time_line = QtCore.QTimeLine(1000*max_value, self) time_line.setFrameRange(0, max_value) time_line.frameChanged.connect(partial(self.update_value, row)) # reset after 3 seconds of completion time_line.finished.connect(lambda r=row: QtCore.QTimer.singleShot(3000, partial(self.reset, r))) time_line.start() def update_value(self, r, i): model = self.tableView.model() ix = model.index(r, 3) model.setData(ix, str(i)) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) w = MainWindow() w.resize(640, 480) w.show() sys.exit(app.exec_())
  • 委托:当模型发生变化并使用值计算颜色时,必须覆盖调用的paint方法,如果颜色与预设不同,则将背景颜色设置为原始模型。 import sys import random from functools import partial from PyQt5 import QtCore, QtGui, QtWidgets def calculate_color(model, row): max_value = int(model.index(row, 2).data()) current_value = int(model.index(row, 3).data()) if current_value == 0: return QtGui.QBrush(QtCore.Qt.white) elif max_value == current_value: return QtGui.QBrush(QtCore.Qt.green) else: return QtGui.QBrush(QtCore.Qt.yellow) class ColorDelegate(QtWidgets.QStyledItemDelegate): def paint(self, painter, option, index): if index.column() in (2, 3): model = index.model() r = index.row() color = calculate_color(model, r) if color != index.data(QtCore.Qt.BackgroundRole): for i in range(model.columnCount()): model.setData(model.index(r, i), color, QtCore.Qt.BackgroundRole) super(ColorDelegate, self).paint(painter, option, index) class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.tableView = QtWidgets.QTableView() self.setCentralWidget(self.tableView) self.model = QtGui.QStandardItemModel() self.model.setHorizontalHeaderLabels(["Prod Name", "EAN","Quanyity", "Counted"]) self.tableView.setModel(self.model) self.tableView.setItemDelegate(ColorDelegate(self)) data = [["Prod1", "123456", 0, 0], ["Prod2", "234567", 0, 0], ["Prod3", "345678", 0, 0]] for r, rowData in enumerate(data): for c, d in enumerate(rowData): it = QtGui.QStandardItem(str(d)) self.model.setItem(r, c, it) # launch test for i in range(self.model.rowCount()): self.reset(i) def reset(self, row): max_value = random.randint(1, 10) self.model.item(row, 2).setText(str(max_value)) self.model.item(row, 3).setText("0") QtCore.QTimer.singleShot(1000, partial(self.start_test, row)) def start_test(self, row): max_value = int(self.model.item(row, 2).text()) time_line = QtCore.QTimeLine(1000*max_value, self) time_line.setFrameRange(0, max_value) time_line.frameChanged.connect(partial(self.update_value, row)) # reset after 3 seconds of completion time_line.finished.connect(lambda r=row: QtCore.QTimer.singleShot(3000, partial(self.reset, r))) time_line.start() def update_value(self, r, i): model = self.tableView.model() ix = model.index(r, 3) model.setData(ix, str(i)) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) w = MainWindow() w.resize(640, 480) w.show() sys.exit(app.exec_())
© www.soinside.com 2019 - 2024. All rights reserved.