zoukankan      html  css  js  c++  java
  • Qt之Model-View架构(雨田哥的博客)

    Qt之Model-View架构

    简述

    为什么会用这个模式,这里我就不解释了,可以看下 豆子哥的见解 。这里我只是如何去使用的。供大家共同探讨学习,主要是参考了Qt的Demo。

    效果图

    这里写图片描述

    代码

    //主代码界面QMvcTest.cpp
    void QMvcTest::initControl()
    {
        QCustomItemModel* customModel = new QCustomItemModel(QJsonArray(), ui.treeView);
        ItemDelegate *delegate = new ItemDelegate(ui.treeView);
        ui.treeView->setModel(customModel);
        delegate->setView(ui.treeView);
        ui.treeView->setAnimated(true);
        ui.treeView->setMouseTracking(true);
        ui.treeView->setItemDelegate(delegate);
        ui.treeView->setCursor(Qt::PointingHandCursor);
    
        const QModelIndex&& curIndex = customModel->index(0, 0).child(0, 0);
        ui.treeView->setCurrentIndex(curIndex);
        connect(delegate, SIGNAL(expanded(const QModelIndex &)), this, SLOT(onTreeViewExpanded(const QModelIndex &)));
    }
    
    void QMvcTest::onTreeViewExpanded(const QModelIndex &index)
    {
        bool bExpanded = ui.treeView->isExpanded(index);
        if (!bExpanded)
        {
            ui.treeView->expand(index);
        }
        else
        {
            ui.treeView->collapse(index);
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    //QCustomItemModel.cpp
    QCustomItemModel::QCustomItemModel(const QJsonArray &data, QObject *parent)
        : QAbstractItemModel(parent)
    {
        QJsonArray objChildArray = { QStringLiteral("雨田哥1号"), QStringLiteral("雨田哥2号"), QStringLiteral("雨田哥3号"), QStringLiteral("雨田哥4号"), QStringLiteral("雨田哥5号") };
        QJsonObject obj{ { QStringLiteral("雨田哥"), objChildArray }
        };
        QJsonArray array = { obj, obj, obj };
    
        QVector<QVariant> rootData;
        rootData << "";
        rootItem = new TreeItem(rootData);
        setModelData(array);
    }
    
    QCustomItemModel::~QCustomItemModel()
    {
        delete rootItem;
    }
    
    int QCustomItemModel::columnCount(const QModelIndex & /* parent */) const
    {
        return rootItem->columnCount();
    }
    
    int QCustomItemModel::rowCount(const QModelIndex &parent) const
    {
        TreeItem *parentItem = getItem(parent);
        return parentItem->childCount();
    }
    
    QVariant QCustomItemModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
            return QVariant();
    
        TreeItem *item = getItem(index);
        if (item == nullptr)
        {
            return QVariant();
        }
    
        if (role == Qt::DisplayRole || role == Qt::EditRole)
        {
            return item->data(index.column());
        }
        else if (role == Qt::UserRole + 1)
        {
            //是否是子节点
            if (item->childCount() == 0)
            {
                return true;
            }
            return false;
        }
        else
        {
            return QVariant();
        }
    }
    
    Qt::ItemFlags QCustomItemModel::flags(const QModelIndex &index) const
    {
        if (!index.isValid())
            return 0;
        TreeItem *item = getItem(index);
        if (item && item->childCount() > 0)
        {
            return Qt::NoItemFlags;
        }
        return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
    }
    
    TreeItem *QCustomItemModel::getItem(const QModelIndex &index) const
    {
        if (index.isValid()) {
            TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
            if (item)
                return item;
        }
        return rootItem;
    }
    
    QVariant QCustomItemModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
        if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
            return rootItem->data(section);
    
        return QVariant();
    }
    
    QModelIndex QCustomItemModel::index(int row, int column, const QModelIndex &parent) const
    {
        if (parent.isValid() && parent.column() != 0)
            return QModelIndex();
        TreeItem *parentItem = getItem(parent);
    
        TreeItem *childItem = parentItem->child(row);
        if (childItem)
            return createIndex(row, column, childItem);
        else
            return QModelIndex();
    }
    
    bool QCustomItemModel::insertColumns(int position, int columns, const QModelIndex &parent)
    {
        bool success;
    
        beginInsertColumns(parent, position, position + columns - 1);
        success = rootItem->insertColumns(position, columns);
        endInsertColumns();
    
        return success;
    }
    
    bool QCustomItemModel::insertRows(int position, int rows, const QModelIndex &parent)
    {
        TreeItem *parentItem = getItem(parent);
        bool success;
    
        beginInsertRows(parent, position, position + rows - 1);
        success = parentItem->insertChildren(position, rows, rootItem->columnCount());
        endInsertRows();
    
        return success;
    }
    
    QModelIndex QCustomItemModel::parent(const QModelIndex &index) const
    {
        if (!index.isValid())
            return QModelIndex();
    
        TreeItem *childItem = getItem(index);
        TreeItem *parentItem = childItem->parent();
    
        if (parentItem == rootItem)
            return QModelIndex();
    
        return createIndex(parentItem->childNumber(), 0, parentItem);
    }
    
    bool QCustomItemModel::removeColumns(int position, int columns, const QModelIndex &parent)
    {
        bool success;
    
        beginRemoveColumns(parent, position, position + columns - 1);
        success = rootItem->removeColumns(position, columns);
        endRemoveColumns();
    
        if (rootItem->columnCount() == 0)
            removeRows(0, rowCount());
    
        return success;
    }
    
    bool QCustomItemModel::removeRows(int position, int rows, const QModelIndex &parent)
    {
        TreeItem *parentItem = getItem(parent);
        bool success = true;
    
        beginRemoveRows(parent, position, position + rows - 1);
        success = parentItem->removeChildren(position, rows);
        endRemoveRows();
    
        return success;
    }
    
    bool QCustomItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
    {
        if (role == Qt::EditRole)
        {
            TreeItem *item = getItem(index);
            bool result = item->setData(index.column(), value);
    
            if (result)
                emit dataChanged(index, index);
            return result;
        }
        else if (role == Qt::FontRole)
        {
            TreeItem *item = getItem(index);
            if (item && item->childCount() == 0)
            {
                item->m_itemFontIsBold = value.toBool();
            }
            return true;
        }
        else
        {
            return false;
        }
    }
    
    bool QCustomItemModel::setHeaderData(int section, Qt::Orientation orientation,
                                  const QVariant &value, int role)
    {
        if (role != Qt::EditRole || orientation != Qt::Horizontal)
            return false;
    
        bool result = rootItem->setData(section, value);
    
        if (result)
            emit headerDataChanged(orientation, section, section);
    
        return result;
    }
    
    void QCustomItemModel::setModelData(const QJsonArray &data)
    {
        for (int nRootIndex = 0; nRootIndex < data.size(); nRootIndex++)
        {
            const QJsonObject&& obj = data.at(nRootIndex).toObject();
            for (auto itor = obj.begin(); itor != obj.end(); itor++)
            {
                const QString&& key = itor.key();
                const QJsonArray&& childAray = itor.value().toArray();
    
                QVector<QVariant> columnData;
                columnData << key;
                rootItem->insertChildren(nRootIndex, 1, rootItem->columnCount());
    
                TreeItem* parent = rootItem->child(nRootIndex);
                parent->setData(0, key);
    
                for (int index = 0; index < childAray.size(); index++)
                {
                    parent->insertChildren(index, 1, rootItem->columnCount());
                    parent->child(index)->setData(0, childAray.at(index).toString());
                }
            }
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    //TreeItem.cpp
    TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent)
    {
        m_itemFontIsBold = true;
        parentItem = parent;
        itemData = data;
    }
    
    TreeItem::~TreeItem()
    {
        qDeleteAll(childItems);
    }
    
    TreeItem *TreeItem::child(int number)
    {
        return childItems.value(number);
    }
    
    int TreeItem::childCount() const
    {
        return childItems.count();
    }
    
    int TreeItem::childNumber() const
    {
        if (parentItem)
            return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
    
        return 0;
    }
    
    int TreeItem::columnCount() const
    {
        return itemData.count();
    }
    
    QVariant TreeItem::data(int column) const
    {
        return itemData.value(column);
    }
    
    bool TreeItem::insertChildren(int position, int count, int columns)
    {
        if (position < 0 || position > childItems.size())
            return false;
    
        for (int row = 0; row < count; ++row) {
            QVector<QVariant> data(columns);
            TreeItem *item = new TreeItem(data, this);
            childItems.insert(position, item);
        }
    
        return true;
    }
    
    bool TreeItem::insertColumns(int position, int columns)
    {
        if (position < 0 || position > itemData.size())
            return false;
    
        for (int column = 0; column < columns; ++column)
            itemData.insert(position, QVariant());
    
        foreach (TreeItem *child, childItems)
            child->insertColumns(position, columns);
    
        return true;
    }
    
    TreeItem *TreeItem::parent()
    {
        return parentItem;
    }
    
    bool TreeItem::removeChildren(int position, int count)
    {
        if (position < 0 || position + count > childItems.size())
            return false;
    
        for (int row = 0; row < count; ++row)
            delete childItems.takeAt(position);
    
        return true;
    }
    
    bool TreeItem::removeColumns(int position, int columns)
    {
        if (position < 0 || position + columns > itemData.size())
            return false;
    
        for (int column = 0; column < columns; ++column)
            itemData.remove(position);
    
        foreach (TreeItem *child, childItems)
            child->removeColumns(position, columns);
    
        return true;
    }
    
    bool TreeItem::setData(int column, const QVariant &value)
    {
        if (column < 0 || column >= itemData.size())
            return false;
    
        itemData[column] = value;
        return true;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    //ItemDelegate.cpp
    void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QStyleOptionViewItem  viewOption(option);
        QStyledItemDelegate::paint(painter, viewOption, index);
    
        bool bExpanded = false;
        if (m_treeView != NULL)
        {
            const QAbstractItemModel *model = index.model();
            if (!model->hasChildren(index))
            {
                return;
            }
            bExpanded = m_treeView->isExpanded(index);
        }
    
        QPixmap pixmap = bExpanded ? QPixmap(m_expandIconName) : QPixmap(m_collapseIconName);
        QRect decorationRect = QRect(viewOption.rect.left() + 14, viewOption.rect.top() + 12, m_pixmapHeight, m_pixmapWidth);
        painter->drawPixmap(decorationRect, pixmap);
    }
    
    bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
    {
        if (event->type() == QEvent::MouseButtonPress && Qt::LeftButton == qApp->mouseButtons())
        {
            m_treeView->update();
            emit expanded(index);
        }
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }
    
    void ItemDelegate::setView(QTreeView *treeView)
    {
        m_treeView = treeView;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    //QSS样式
    QTreeView
    {
        background-color: #ffffff;
        show-decoration-selected: 1;
        outline:0px;
    }
    
    QTreeView::item {
        background-color:transparent;
        font-family: Microsoft YaHei;
        font-size: 12px;
        color: #666666;
        text-align:left;
        height:32px;
        padding-left:22px;
    }
    
    QTreeView::item:has-children {
        background-color:transparent;
        font-family: Microsoft YaHei;
        font-size: 12px;
        color: #333333;
        text-align:left;
        height:32px;
        padding-left:22px;
    }
    
    QTreeView::item:hover,QTreeView::item:selected {
        background-color:#D3EFFF;
        font-size: 12px;
        color: #00A1FF;
        border:0px;
        text-align:left;
    }
    
    QTreeView::branch:has-children:!has-siblings:closed,
    QTreeView::branch:closed:has-children:has-siblings {
        border-image: none;
        image: url(:/QMvcTest/Resources/smallPackup.png:);
    }
    
    QTreeView::branch:open:has-children:!has-siblings,
    QTreeView::branch:open:has-children:has-siblings  {
        border-image: none;
        image: url(:/QMvcTest/Resources/smallExp.png);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    结尾

    只为记录,只为分享! 愿所写能对你有所帮助。不忘记点个赞,谢谢~ 
    需要原工程文件的可以加我QQ,因权限问题暂时不能上传工程文件。

    http://blog.csdn.net/ly305750665/article/details/79016794

  • 相关阅读:
    *洛谷P1858 多人背包
    ZOJ3469 Food Delivery
    Hdu5115 Dire Wolf
    Codevs 2765 隐形的翅膀
    Hdu4055 Number String
    Codevs 1300 文件排版
    洛谷 P1412 经营与开发
    Codevs 4357 不等数列
    codevs 3333 高级打字机
    Bzoj 1086: [SCOI2005]王室联邦
  • 原文地址:https://www.cnblogs.com/findumars/p/6181656.html
Copyright © 2011-2022 走看看