QT 设置在代理模型中读取数据库数据、排序

源模型:

  • 源模型是数据的提供者,通常是继承自QAbstractItemModel的类。
  • 它负责存储和管理数据,提供对数据的访问和操作接口。
  • 源模型可以是树形结构、表格结构或其他自定义结构的数据模型。

代理模型:

  • 代理模型是源模型的中间层,可以在不改变源模型的情况下修改视图的行为和外观。
  • 代理模型是QAbstractProxyModel类的子类,通过继承和重写相关函数来实现自定义的转换和过滤逻辑。
  • 代理模型可以用于对源模型的数据进行排序、过滤、映射、重组等操作,以适应不同的视图需求。

委托模型:

  • 委托模型用于自定义视图中数据项的外观和编辑方式。
  • 委托模型是QAbstractItemDelegate类的子类,通过继承和重写相关函数来实现自定义的绘制和编辑逻辑。
  • 委托模型可以用于自定义数据项的展示方式,例如使用不同的图标、颜色、字体等进行绘制,并提供自定义的编辑器部件用于编辑数据项。


通过使用代理模型和委托模型,可以实现以下功能:

  • 数据过滤和排序:代理模型可以根据特定的条件对源模型中的数据进行过滤或排序,以满足特定的视图需求。
  • 数据映射和重组:代理模型可以对源模型中的数据进行映射或重组,以改变数据的结构或表示形式。
  • 视图外观自定义:委托模型可以自定义视图中数据项的外观,例如使用不同的图标、颜色、字体等进行绘制,以提供更丰富的用户界面。
  • 自定义编辑器:委托模型可以提供自定义的编辑器部件,用于修改数据项的值,并将修改后的值反映回源模型。
  • 通过将源模型、代理模型和委托模型结合使用,可以实现灵活强大的数据模型和视图的组合,使开发者能够更好地管理和展示数据,并提供交互性的用户界面。

源模型读取数据库数据:

  if (device)
  {
    _query.query("WHERE Device = :RFID");
    _query.bind(":RFID", (long long)device->getRFID());
  }
  else
  {
    _query.query("");
  }

首先在源模型中获取数据库中存储的数据,如果匹配到数据就进行绑定,如果没有找到数据就清空查询。

源模型中设置好数据的读取,首先获取给定部分的头部数据,然后检查数据的方向,如果方向是水平的并且角色是显示角色,那么它会进一步检查头部数据的值,然后根据不同的值返回对应的数据。(这里直接显示获取到的数据,如果获取时数据类型不符需要转换为QString类型

auto retData = d_StdLock_model::headerData(section, orientation, role);

  if (orientation == Qt::Orientation::Horizontal && role == Qt::DisplayRole)
  {
    auto header = retData.toString();
    if (header == RFID())
    {
      retData = RFID();
    }
  }

在代理模型中的排序:

首先检查设置的两个索引列是否是RFID所在列,

如果是,那么它会从源模型中获取对应索引的数据,并且将这些数据转换为字符串进行比较。如果左边的数据小于右边的数据,那么函数返回true,否则返回false

如果两个索引的列不是,那么函数将调用父类的lessThan方法来比较两个索引。

bool StdLocksListProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
{
  if (left.column() == _RFIDIndex && right.column() == _RFIDIndex)
  {
    QVariant leftData = sourceModel()->data(left);
    QVariant rightData = sourceModel()->data(right);
    return leftData.toString() < rightData.toString();
  }
  return QSortFilterProxyModel::lessThan(left, right);
}

 如果想让你设置出一个背景色来填充有相同数据的列应该怎么做呢,如果还有对模型视图的更多要求的话可以使用委托模型来使用,在这里只有设置高亮的要求,所以我直接在代理模型中进行了设置。

data函数:

  • 首先,通过检查role参数的值,判断是否是要处理背景色的请求。
  • 进一步检查是否有按钮被点击。
  • 获取源模型中对应索引的数据,使用mapToSource函数将代理模型中的索引映射到源模型中的索引。
  • 检查当前索引所在列是否为RFID列。
  • 检查上一行和下一行的数据是否与当前行的数据相同,如果相同,为该行设置特定的背景色。
  • 获取颜色映射表(colorMap)。
  • 如果颜色映射表中已经包含了当前行的数据,从映射表中获取对应的颜色;否则,根据映射表的大小选择不同的颜色,并将当前行的数据和颜色添加到映射表中。
  • 使用获取到的颜色创建QBrush对象,并将其作为结果返回。

getColorMap函数:

用于获取静态的颜色映射表。该函数返回一个QMap<QVariant, QColor>类型的静态变量colorMap,确保在多次调用时返回相同的映射表。 

QVariant StdLocksListProxyModel::data(const QModelIndex& index, int role) const
{
  if (role == Qt::BackgroundRole)
  {
    if (buttonClicked)
    {
      QModelIndex sourceIndex = mapToSource(index);
      if (sourceIndex.column() == _RFIDIndex)
      {
        QVariant currentRfidData = sourceModel()->data(sourceIndex, Qt::DisplayRole);

        // 检查上一行
        if (index.row() > 0)
        {
          QModelIndex previousIndex = this->index(index.row() - 1, sourceIndex.column());
          QVariant previousRfidData = sourceModel()->data(mapToSource(previousIndex), Qt::DisplayRole);
          if (currentRfidData == previousRfidData)
          {
            QMap<QVariant, QColor>& colorMap = getColorMap();
            QColor color;
            if (colorMap.contains(currentRfidData))
            {
              color = colorMap.value(currentRfidData);
            }
            else
            {
              if (colorMap.size() % 2 == 0)
              {
                color = QColor(Qt::yellow);
              }
              else
              {
                color = QColor(Qt::cyan);
              }
              colorMap.insert(currentRfidData, color);
            }
            QBrush brush(color);
            return brush;
          }
        }
        if (index.row() < rowCount() - 1)
        {
          QModelIndex nextIndex = this->index(index.row() + 1, sourceIndex.column());
          QVariant nextRfidData = sourceModel()->data(mapToSource(nextIndex), Qt::DisplayRole);
          if (currentRfidData == nextRfidData)
          {
            QMap<QVariant, QColor>& colorMap = getColorMap();
            QColor color;
            if (colorMap.contains(currentRfidData))
            {
              color = colorMap.value(currentRfidData);
            }
            else
            {
              if (colorMap.size() % 2 == 0)
              {
                color = QColor(Qt::yellow);
              }
              else
              {
                color = QColor(Qt::cyan);
              }
              colorMap.insert(currentRfidData, color);
            }
            QBrush brush(color);
            return brush;
          }
        }
      }
    }
  }
  return QSortFilterProxyModel::data(index, role);
}

QMap<QVariant, QColor>& StdLocksListProxyModel::getColorMap() const
{
  static QMap<QVariant, QColor> colorMap;
  return colorMap;
}

 因为有less Than的排序,所以可以使用上下行判断进行排序,如果数据量不大也可以使用遍历的方法进行筛选相同数据。

本文只设置了模型的显示情况,按钮点击功能并没有在代理模型中设置,如果需要在视图中显示出来还需要自行设置一下widget页面来完成视图的显示和按钮点击情况。

 QVariant :

 用于封装复杂数据类型的类,可以保存多种类型的数据,可以用来在Qt程序中处理和保存各种类型的值。常见的Qt类型如QColor、QBrush、QFont、QRect、QString和QSize等,同时也能保存Qt的容器类型值。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值