【问题标题】:Change color of rows depending on user input in a QTableView根据 QTableView 中的用户输入更改行的颜色
【发布时间】:2019-02-06 05:53:25
【问题描述】:

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

总体目标是提供一种快速简便的方法来确保以正确的顺序放置正确的产品。

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

我想要实现的示例。

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qtableview


    【解决方案1】:

    有以下选择:

    • QIdentityProxyModel:你必须覆盖data方法,你用数值计算颜色,如果颜色和预设不一样,把背景颜色设置为原来的模型。

      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_())
      
    • Delegate:必须覆盖模型发生变化时调用的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_())
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-21
      • 1970-01-01
      • 1970-01-01
      • 2020-09-20
      • 2019-09-17
      • 1970-01-01
      • 2021-08-29
      • 1970-01-01
      相关资源
      最近更新 更多