Qt QTable等 3种代理详细解析

         对于QtableView,QTreeView等组件的代理,只存在一些零零散散的代码演示,对于具体怎么做却没多少人写出,本文针对这三种代理(这3种代理都以QAbstractItemDelegate为父类,主要针对不同种情况)给出较为详细的中文解释:

  • 1.QStyledItemDelegate

从名字就可以看出,这个代理主要服务内容就是表中一行,树中一枝的样式风格。官方也有对其解释:

QStyledItemDelegate implements display and editing for the most common datatypes expected by users, including booleans, integers, and strings.

主要指其实现了用户期望的最常见数据类型的显示和编辑,包括布尔值、整数和字符串。

常用方法主要有3个:

[override virtual] QWidget *QStyledItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const

[override virtual] void QStyledItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const

[override virtual] void QStyledItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const

其中creaeEditer 返回用于编辑由索引指定的项目以进行编辑的小部件。父窗口小部件和样式选项用于控制编辑器窗口小部件的显示方式。其实就是对表中一格插入一个多选框、下拉框等小部件。

QWidget *MyDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &/* option */,
    const QModelIndex & index ) const
{
    if(index.column() == 1)
    {
        QComboBox* box = new QComboBox(parent);
        box->addItems(QStringList()<<"1"<<"2"<<"3");
        return box;
    }
    return NULL;
}

如图中所示,其实就是在一个单元格中生成一个下拉框。

paint函数多用于调整表格中文字或位置。

void qTableView_Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem new_option(option);
    new_option.displayAlignment = Qt::AlignCenter;        // 居中显示

    if (new_option.state & QStyle::State_Selected) {
        new_option.font.setBold(true);                    // 变为粗体
    }
    QStyledItemDelegate::paint(painter, new_option, index);
}

setEditorData往往用来调整小组件中数据显示

void MyDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    QString value = index.model()->data(index, Qt::EditRole).toString();
    QComboBox* box = static_cast<QComboBox*>(editor);
    box->setCurrentText(value);
}
  •  2.QIdentityProxyModel

这种代理主要针对来自数据库或者其他位置数据的二次封装。官方解释为:

QIdentityProxyModel can be used to forward the structure of a source model exactly, with no sorting, filtering or other transformation. This is similar in concept to an identity matrix where A.I = A.
Because it does no sorting or filtering, this class is most suitable to proxy models which transform the data() of the source model. For example, a proxy model could be created to define the font used, or the background colour, or the tooltip etc. This removes the need to implement all data handling in the same class that creates the structure of the model, and can also be used to create re-usable components.
This also provides a way to change the data in the case where a source model is supplied by a third party which cannot be modified.

这种方式主要内容与QStyledItemDelegate有一部分类似,但是其提供了一种重要内容,那就是当我们获取数据并不是从数据库等可以修改处拿来数据时,可以在不修改其原内容的基础上,在页面上进行修改。

class DateFormatProxyModel : public QIdentityProxyModel
 {
   // ...

   void setDateFormatString(const QString &formatString)
   {
     m_formatString = formatString;
   }

   QVariant data(const QModelIndex &index, int role) const override
   {
     if (role != Qt::DisplayRole)
       return QIdentityProxyModel::data(index, role);

     const QDateTime dateTime = sourceModel()->data(SourceClass::DateRole).toDateTime();

     return dateTime.toString(m_formatString);
   }

 private:
   QString m_formatString;
 };

 如这段代码就是对其输入类型进行了转换。

  • 3.QSortFilterProxyModel

这个类是对获得的数据进行排序,其不改变原数据。官方定义为;

QSortFilterProxyModel can be used for sorting items, filtering out items, or both. The model transforms the structure of a source model by mapping the model indexes it supplies to new indexes, corresponding to different locations, for views to use. This approach allows a given source model to be restructured as far as views are concerned without requiring any transformations on the underlying data, and without duplicating the data in memory.

 其主要是用来筛选和对数据进行排序

bool MySortFilterProxyModel::lessThan(const QModelIndex &left,
                                       const QModelIndex &right) const
 {
     QVariant leftData = sourceModel()->data(left);
     QVariant rightData = sourceModel()->data(right);

     if (leftData.userType() == QMetaType::QDateTime) {
         return leftData.toDateTime() < rightData.toDateTime();
     } else {
         static const QRegularExpression emailPattern("[\\w\\.]*@[\\w\\.]*");

         QString leftString = leftData.toString();
         if (left.column() == 1) {
             const QRegularExpressionMatch match = emailPattern.match(leftString);
             if (match.hasMatch())
                 leftString = match.captured(0);
         }
         QString rightString = rightData.toString();
         if (right.column() == 1) {
             const QRegularExpressionMatch match = emailPattern.match(rightString);
             if (match.hasMatch())
                 rightString = match.captured(0);
         }

         return QString::localeAwareCompare(leftString, rightString) < 0;
     }
 }
 bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,
                                               const QModelIndex &sourceParent) const
 {
     QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
     QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
     QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent);

     return (sourceModel()->data(index0).toString().contains(filterRegExp())
             || sourceModel()->data(index1).toString().contains(filterRegExp()))
             && dateInRange(sourceModel()->data(index2).toDate());
 }

上面两段分别是数据进行排序和筛选。使用时,只需要将其加入到自己设计的model中即可。

 QTreeView *treeView = new QTreeView;
         MyItemModel *sourceModel = new MyItemModel(this);
         QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);

         proxyModel->setSourceModel(sourceModel);
         treeView->setModel(proxyModel);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值