Qt之Model-View架构(雨田哥的博客)
阅读原文时间:2023年07月15日阅读:1
  • * Qt之Model-View架构

    *   [简述](http://blog.csdn.net/ly305750665/article/details/79016794#%E7%AE%80%E8%BF%B0)
    *   [效果图](http://blog.csdn.net/ly305750665/article/details/79016794#%E6%95%88%E6%9E%9C%E5%9B%BE)
    *   [代码](http://blog.csdn.net/ly305750665/article/details/79016794#%E4%BB%A3%E7%A0%81)
    *   [结尾](http://blog.csdn.net/ly305750665/article/details/79016794#%E7%BB%93%E5%B0%BE)

简述

为什么会用这个模式,这里我就不解释了,可以看下 豆子哥的见解 。这里我只是如何去使用的。供大家共同探讨学习,主要是参考了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(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-&gt;child(nRootIndex);
        parent-&gt;setData(0, key);
    
        for (int index = 0; index &lt; childAray.size(); index++)
        {
            parent-&gt;insertChildren(index, 1, rootItem-&gt;columnCount());
            parent-&gt;child(index)-&gt;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 &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(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