源模型:
- 源模型是数据的提供者,通常是继承自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的容器类型值。