日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt 可编辑的树模型(Tree Model)的一个实例

發布時間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt 可编辑的树模型(Tree Model)的一个实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本實例來自Qt 官方的一個實例(Editable Tree Model Example)

簡介:
本實例是關于怎樣基于模式視圖框架下的 樹模型的實現。


該模型支持可編輯的表單項,自定義表頭,刪除插入行和列,也可以插入子表單項。

在標準數據模型中提供了這些函數:
flags()、data()、headerData()、columnCount()、rowCount()。
因為本實例還具有繼承的關系,所以還需要index()、parent()兩個函數。

一個可編輯的模型還需要實現setData()、和setHeaderData(),同時還需要一個狀態機制flags()。

由于該實例還需要實現行列變化,所以我們還需要實現insertRows()、insertColumns()、removeRows()、removeColumn()。

設計:

1、樹狀數據模型的內部關系:

從上圖中可以看到:樹狀數據模型中的每一數據項都包含它的父項(parent())和子項(child())信息。

每一個數據項(itemData)依據行和列信息進行存儲。我們可以通過簡單的data()函數來遍歷整個數據項(itemData list);通過setData()來修改數據項(itemData)

根節點(root Item)相當于一個空數據索引,用QModelIndex()來指定。

樹狀數據模型的訪問:

如圖:數據項可以通過行和列以及它的父項信息進行訪問:

QVariant a = model->index(0, 0, QModelIndex()).data();

QVariant b = model->index(1, 0, QModelIndex()).data();

樹狀數據模型的存儲結構:

數據項的存儲類似QVariant 對象。


通過數據索引來構建數據項的內在關系:
(Relating items using model indexes)

樹狀模型數據項的類定義:

class TreeItem{public:explicit TreeItem(const QVector<QVariant> &data, TreeItem *parent = nullptr);~TreeItem();TreeItem *child(int number);int childCount() const;int columnCount() const;QVariant data(int column) const;bool insertChildren(int position, int count, int columns);bool insertColumns(int position, int columns);TreeItem *parent();bool removeChildren(int position, int count);bool removeColumns(int position, int columns);int childNumber() const;bool setData(int column, const QVariant &value);private:QVector<TreeItem*> childItems;QVector<QVariant> itemData;TreeItem *parentItem;};

樹狀數據模型類的成員實現:

1、構造函數: 構建數據項

TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent): itemData(data),parentItem(parent){}

2、析構函數: 確保當一個數據項刪除的時候,那么它的所有子項都會被刪除。

TreeItem::~TreeItem(){qDeleteAll(childItems);}

3、parent(),每個數據項都存有指針指向它的父項

TreeItem *TreeItem::parent(){return parentItem;}

4、三個函數提供關于子項的信息:
child()、childCount()、childNumber()

TreeItem *TreeItem::child(int number){if (number < 0 || number >= childItems.size())return nullptr;return childItems.at(number);}int TreeItem::childCount() const{return childItems.count();}int TreeItem::childNumber() const{if (parentItem)return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));return 0;}

5、columnCount() :

int TreeItem::columnCount() const{return itemData.count();}

6、獲取數據data():

QVariant TreeItem::data(int column) const{if (column < 0 || column >= itemData.size())return QVariant();return itemData.at(column);}

7、修改數據

bool TreeItem::setData(int column, const QVariant &value){if (column < 0 || column >= itemData.size())return false;itemData[column] = value;return true;}

8、子節點數據的插入

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;}

9、子節點數據的刪除:

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;}

10、插入列:

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());for (TreeItem *child : qAsConst(childItems))child->insertColumns(position, columns);return true;}

樹狀模型類的定義:

class TreeModel : public QAbstractItemModel{Q_OBJECTpublic:TreeModel(const QStringList &headers, const QString &data,QObject *parent = nullptr);~TreeModel();//The constructor and destructor are specific to this model.QVariant data(const QModelIndex &index, int role) const override;QVariant headerData(int section, Qt::Orientation orientation,int role = Qt::DisplayRole) const override;QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const override;QModelIndex parent(const QModelIndex &index) const override;int rowCount(const QModelIndex &parent = QModelIndex()) const override;int columnCount(const QModelIndex &parent = QModelIndex()) const override;//Read-only tree models only need to provide the above functions. The following public functions provide support for editing and resizing:Qt::ItemFlags flags(const QModelIndex &index) const override;bool setData(const QModelIndex &index, const QVariant &value,int role = Qt::EditRole) override;bool setHeaderData(int section, Qt::Orientation orientation,const QVariant &value, int role = Qt::EditRole) override;bool insertColumns(int position, int columns,const QModelIndex &parent = QModelIndex()) override;bool removeColumns(int position, int columns,const QModelIndex &parent = QModelIndex()) override;bool insertRows(int position, int rows,const QModelIndex &parent = QModelIndex()) override;bool removeRows(int position, int rows,const QModelIndex &parent = QModelIndex()) override;private:void setupModelData(const QStringList &lines, TreeItem *parent);TreeItem *getItem(const QModelIndex &index) const;TreeItem *rootItem;};

樹狀模型類的成員實現:

1、構造函數: 創建根節點和表頭數據項

TreeModel::TreeModel(const QStringList &headers, const QString &data, QObject *parent): QAbstractItemModel(parent){QVector<QVariant> rootData;for (const QString &header : headers)rootData << header;rootItem = new TreeItem(rootData);setupModelData(data.split('\n'), rootItem);}

2、析構函數:

TreeModel::~TreeModel(){delete rootItem;}

3、獲取數據項:

TreeItem *TreeModel::getItem(const QModelIndex &index) const{if (index.isValid()) {TreeItem *item = static_cast<TreeItem*>(index.internalPointer());if (item)return item;}return rootItem;}

4、行統計:

int TreeModel::rowCount(const QModelIndex &parent) const{const TreeItem *parentItem = getItem(parent);return parentItem ? parentItem->childCount() : 0;}

5、列統計:

int TreeModel::columnCount(const QModelIndex &parent) const{Q_UNUSED(parent);return rootItem->columnCount();}

6、flags()

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const{if (!index.isValid())return Qt::NoItemFlags;return Qt::ItemIsEditable | QAbstractItemModel::flags(index);}

7、創建數據索引

QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const{if (parent.isValid() && parent.column() != 0)return QModelIndex();TreeItem *parentItem = getItem(parent);if (!parentItem)return QModelIndex();TreeItem *childItem = parentItem->child(row);if (childItem)return createIndex(row, column, childItem);return QModelIndex();}

8、parent()

QModelIndex TreeModel::parent(const QModelIndex &index) const{if (!index.isValid())return QModelIndex();TreeItem *childItem = getItem(index);TreeItem *parentItem = childItem ? childItem->parent() : nullptr;if (parentItem == rootItem || !parentItem)return QModelIndex();return createIndex(parentItem->childNumber(), 0, parentItem);}

主函數類:

/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/#ifndef MAINWINDOW_H #define MAINWINDOW_H#include "ui_mainwindow.h"#include <QMainWindow>class MainWindow : public QMainWindow, private Ui::MainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);public slots:void updateActions();private slots:void insertChild();bool insertColumn();void insertRow();bool removeColumn();void removeRow(); };#endif // MAINWINDOW_H

主函數成員實現:

/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/#include "mainwindow.h" #include "treemodel.h"#include <QFile>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {setupUi(this);const QStringList headers({tr("Title"), tr("Description")});QFile file(":/default.txt");file.open(QIODevice::ReadOnly);TreeModel *model = new TreeModel(headers, file.readAll());file.close();view->setModel(model);for (int column = 0; column < model->columnCount(); ++column)view->resizeColumnToContents(column);connect(exitAction, &QAction::triggered, qApp, &QCoreApplication::quit);connect(view->selectionModel(), &QItemSelectionModel::selectionChanged,this, &MainWindow::updateActions);connect(actionsMenu, &QMenu::aboutToShow, this, &MainWindow::updateActions);connect(insertRowAction, &QAction::triggered, this, &MainWindow::insertRow);connect(insertColumnAction, &QAction::triggered, this, &MainWindow::insertColumn);connect(removeRowAction, &QAction::triggered, this, &MainWindow::removeRow);connect(removeColumnAction, &QAction::triggered, this, &MainWindow::removeColumn);connect(insertChildAction, &QAction::triggered, this, &MainWindow::insertChild);updateActions(); }void MainWindow::insertChild() {const QModelIndex index = view->selectionModel()->currentIndex();QAbstractItemModel *model = view->model();if (model->columnCount(index) == 0) {if (!model->insertColumn(0, index))return;}if (!model->insertRow(0, index))return;for (int column = 0; column < model->columnCount(index); ++column) {const QModelIndex child = model->index(0, column, index);model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);if (!model->headerData(column, Qt::Horizontal).isValid())model->setHeaderData(column, Qt::Horizontal, QVariant(tr("[No header]")), Qt::EditRole);}view->selectionModel()->setCurrentIndex(model->index(0, 0, index),QItemSelectionModel::ClearAndSelect);updateActions(); }bool MainWindow::insertColumn() {QAbstractItemModel *model = view->model();int column = view->selectionModel()->currentIndex().column();// Insert a column in the parent item.bool changed = model->insertColumn(column + 1);if (changed)model->setHeaderData(column + 1, Qt::Horizontal, QVariant("[No header]"), Qt::EditRole);updateActions();return changed; }void MainWindow::insertRow() {const QModelIndex index = view->selectionModel()->currentIndex();QAbstractItemModel *model = view->model();if (!model->insertRow(index.row()+1, index.parent()))return;updateActions();for (int column = 0; column < model->columnCount(index.parent()); ++column) {const QModelIndex child = model->index(index.row() + 1, column, index.parent());model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);} }bool MainWindow::removeColumn() {QAbstractItemModel *model = view->model();const int column = view->selectionModel()->currentIndex().column();// Insert columns in each child of the parent item.const bool changed = model->removeColumn(column);if (changed)updateActions();return changed; }void MainWindow::removeRow() {const QModelIndex index = view->selectionModel()->currentIndex();QAbstractItemModel *model = view->model();if (model->removeRow(index.row(), index.parent()))updateActions(); }void MainWindow::updateActions() {const bool hasSelection = !view->selectionModel()->selection().isEmpty();removeRowAction->setEnabled(hasSelection);removeColumnAction->setEnabled(hasSelection);const bool hasCurrent = view->selectionModel()->currentIndex().isValid();insertRowAction->setEnabled(hasCurrent);insertColumnAction->setEnabled(hasCurrent);if (hasCurrent) {view->closePersistentEditor(view->selectionModel()->currentIndex());const int row = view->selectionModel()->currentIndex().row();const int column = view->selectionModel()->currentIndex().column();if (view->selectionModel()->currentIndex().parent().isValid())statusBar()->showMessage(tr("Position: (%1,%2)").arg(row).arg(column));elsestatusBar()->showMessage(tr("Position: (%1,%2) in top level").arg(row).arg(column));} }

總結:花了一個上午的時間分析了這個樹狀數據模式的視圖實現,抽象數據原本就相對難理解,這個模型和數據類的定義內容還是挺多的,需要逐步消化。

總結

以上是生活随笔為你收集整理的Qt 可编辑的树模型(Tree Model)的一个实例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。