什么样的网站开发比较吃香,静态网页制作方法,宣传推广策略,重庆搜狗推广【嵌入式——QT】Model/View 基本原理数据模型视图组件代理Model/View结构的一些概念QFileSystemModelQStringListModelQStandardItemModel自定义代理 基本原理
GUI应用程序的一个很重要的功能是由用户在界面上编辑和修改数据#xff0c;典型的如数据库应用程序#xff0c;数… 【嵌入式——QT】Model/View 基本原理数据模型视图组件代理Model/View结构的一些概念QFileSystemModelQStringListModelQStandardItemModel自定义代理 基本原理
GUI应用程序的一个很重要的功能是由用户在界面上编辑和修改数据典型的如数据库应用程序数据库应用程序中用户在界面上执行各种操作实际上是修改了界面组件所关联的数据库内的数据。将界面组件与所编辑的数据分离开来又通过数据源的方式连接起来是处理界面与数据的一种较好的方式Qt使用Model/View结构来处理这种关系。
数据模型
QAbstractItemModel
QAbstractListModelQStringListModel处理字符串列表数据的数据模型类QAbstractProxyModelQSortFilterProxyModel提供排序和过滤功能的数据模型类QAbstractTableModelQSqlQueryModel数据库SQL查询结构的数据模型类QSqlTableModel用于数据库的一个数据表的数据模型类QSqlRelationalTableModel关系型数据表的数据模型类QStandardItemModel每个项数据可以使任何数据类型QFileSystemModel文件系统的数据模型类
视图组件
QListView用于显示单列的列表数据适用于一维数据的操作QTreeView用于显示树状结构数据适用于树状结构数据的操作QTableView用于显示表格状数据适用于二维表格型数据的操作QColumnView用多个QListView显示树状层次结构树状结构的一层用一个QListView显示QHeaderView提供行表头或列表头的视图组件如QTableView的行表头和列表头
代理
代理(Delegate)就是在视图组件上为编辑数据提供编辑器如在表格组件中编辑一个单元格的数据时缺省是使用一个QLineEdit编辑框。 代理负责从数据模型获取相应的数据然后显示在编辑器里修改数据后又将其保存到数据模型中。 QAbstractItemDelegate是所有代理类的基类它不能直接使用它的一个子类QStyledItemDelegate是Qt的视图组件缺省使用的代理类。
Model/View结构的一些概念
基本结构 数据模型中的存储数据的基本单元都是项(item)每个项都有一个行号一个列号还有一个父项。 模型索引 QModelIndex表示模型索引的类模型索引提供数据存取的一个临时指针用于通过数据模型提取或修改数据因为模型内部数据的结构随时可能改变所以模型索引是临时的。 行号和列号 数据模型的基本形式是用行和列定义的表格数据要获得一个模型索引必须提供行号、列号、父项的模型索引。 父项 当数据模型是列表或表格时使用行号、列号存储数据比较直观所有数据项的父项就是顶层项当数据模型是树状结构时情况比较复杂一个节点可以有父节点也可以是其他节点的父节点在构造数据项的模型索引时必须指定正确的行号、列号和父节点。 项的角色 在为数据模式的一个项设置数据时可以赋予其不同项的角色的数据。 enum ItemDataRole
Qt::DisplayRole在视图组件中显示字符串标准角色Qt::ToolTipRole鼠标提示消息Qt::UserRole可以自定义数据
QFileSystemModel
QFileSystemModel提供了一个可用于访问本机文件系统的数据模型QFileSystemModel和视图组件QTreeView结合使用可以用目录树的形式显示本机上的文件系统如同Windows的资源管理器一样使用QFileSystemModel提供的接口函数可以创建目录删除目录重命名目录可以获得文件名称、目录名称、文件大小等参数还可以获得文件的详细信息。 图示
代码示例 ModelViewDialog.h
#ifndef MODELVIEWDIALOG_H
#define MODELVIEWDIALOG_H#include QDialog
#include QFileSystemModelnamespace Ui
{class ModelViewDialog;
}class ModelViewDialog : public QDialog
{Q_OBJECTpublic:explicit ModelViewDialog(QWidget* parent nullptr);~ModelViewDialog();
private slots:void on_treeView_clicked(const QModelIndex index);private:Ui::ModelViewDialog* ui;QFileSystemModel* model;
};#endif // MODELVIEWDIALOG_H
ModelViewDialog.cpp
#include ModelViewDialog.h
#include ui_ModelViewDialog.h
ModelViewDialog::ModelViewDialog(QWidget* parent): QDialog(parent), ui(new Ui::ModelViewDialog)
{ui-setupUi(this);model new QFileSystemModel(this);//QDir::currentPath() 获得本机文件系统model-setRootPath(QDir::currentPath());//设置根目录ui-treeView-setModel(model);//设置数据模型ui-listView-setModel(model);//设置数据模型ui-tableView-setModel(model);//设置数据模型connect(ui-treeView, SIGNAL(clicked(QModelIndex)), ui-listView, SLOT(setRootIndex(QModelIndex)));connect(ui-treeView, SIGNAL(clicked(QModelIndex)), ui-tableView, SLOT(setRootIndex(QModelIndex)));
}ModelViewDialog::~ModelViewDialog()
{delete ui;
}void ModelViewDialog::on_treeView_clicked(const QModelIndex index)
{ui-checkBox-setChecked(model-isDir(index));//是否目录ui-labPath-setText(model-filePath(index));//返回节点的目录名或带路径的文件名ui-labType-setText(model-type(index));//返回描述节点类型的文字ui-labFileName-setText(model-fileName(index));//返回去除路径的文件夹名称或文件名int sz model-size(index)/1024;//如果节点是文件返回文件大小的字节数如果节点是文件夹返回0if(sz1024) {ui-labSize-setText(QString(%1 KB).arg(sz));} else {ui-labSize-setText(QString::asprintf(%.1f MB, sz/1024.0));}
}
QStringListModel
QStringListModel用于处理字符串列表的数据模型它可以作为QListView的数据模型在界面上显示和编辑字符串列表。
图示
代码示例
QStringListModelDialog.h
#ifndef QSTRINGLISTMODELDIALOG_H
#define QSTRINGLISTMODELDIALOG_H#include QDialog
#include QStringListModelnamespace Ui
{class QStringListModelDialog;
}class QStringListModelDialog : public QDialog
{Q_OBJECTpublic:explicit QStringListModelDialog(QWidget* parent nullptr);~QStringListModelDialog();private slots:void on_pushButtonAdd_clicked();void on_pushButtonInsert_clicked();void on_pushButtonRemove_clicked();void on_pushButtonClear_clicked();void on_pushButtonShow_clicked();void on_listView_clicked(const QModelIndex index);void on_pushButtonReset_clicked();void on_pushButtonClearText_clicked();private:Ui::QStringListModelDialog* ui;QStringListModel* model;
};#endif // QSTRINGLISTMODELDIALOG_H
QStringListModelDialog.cpp
#include QStringListModelDialog.h
#include ui_QStringListModelDialog.h
QStringListModelDialog::QStringListModelDialog(QWidget* parent): QDialog(parent), ui(new Ui::QStringListModelDialog)
{ui-setupUi(this);QStringList theStrList;theStrList北京上海天津河北河南山东;model new QStringListModel(this);//将一个字符串列表的内容作为数据模型的初始化数据内容model-setStringList(theStrList);ui-listView-setModel(model);//双击 或 选择并单击后进入编辑状态ui-listView-setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
}QStringListModelDialog::~QStringListModelDialog()
{delete ui;
}void QStringListModelDialog::on_pushButtonAdd_clicked()
{model-insertRow(model-rowCount());//在尾部插入一行QModelIndex index model-index(model-rowCount()-1, 0);model-setData(index, new item, Qt::DisplayRole);ui-listView-setCurrentIndex(index);//设置当前选中的行
}void QStringListModelDialog::on_pushButtonInsert_clicked()
{QModelIndex index ui-listView-currentIndex();model-insertRow(index.row());model-setData(index, inserted item, Qt::DisplayRole);ui-listView-setCurrentIndex(index);
}void QStringListModelDialog::on_pushButtonRemove_clicked()
{QModelIndex index ui-listView-currentIndex();model-removeRow(index.row());
}void QStringListModelDialog::on_pushButtonClear_clicked()
{model-removeRows(0, model-rowCount());
}void QStringListModelDialog::on_pushButtonShow_clicked()
{QStringList tmpList model-stringList();ui-plainTextEdit-clear();for(int i0; itmpList.count(); i) {ui-plainTextEdit-appendPlainText(tmpList.at(i));}
}void QStringListModelDialog::on_listView_clicked(const QModelIndex index)
{ui-label-setText(QString::asprintf(current:row%d,column%d, index.row(), index.column()));
}void QStringListModelDialog::on_pushButtonReset_clicked()
{model-removeRows(0, model-rowCount());QStringList theStrList;theStrList北京上海天津河北河南山东;model-setStringList(theStrList);
}void QStringListModelDialog::on_pushButtonClearText_clicked()
{ui-plainTextEdit-clear();
}
QStandardItemModel
QStandardItemModel是标准的以项数据为基础的标准数据模型类通常与QTableView组合成Model/View结构。实现通用的二维数据的管理功能。
图示
代码示例 QStandardItemModelDialog.h
#ifndef QSTANDARDITEMMODELDIALOG_H
#define QSTANDARDITEMMODELDIALOG_H#include QDialog
#include QLabel#include QStandardItemModel
#include QItemSelectionModel
#define FixedColumnCount 6
namespace Ui
{class QStandardItemModelDialog;
}class QStandardItemModelDialog : public QDialog
{Q_OBJECTpublic:explicit QStandardItemModelDialog(QWidget* parent nullptr);~QStandardItemModelDialog();void initModelFromStringList(QStringList fFileContent);public slots:void on_currentChanged(const QModelIndex current, const QModelIndex previous);private slots:void on_pushButtonOpen_clicked();void on_pushButtonAdd_clicked();void on_pushButtonInsert_clicked();void on_pushButtonRemove_clicked();void on_pushButtonLeft_clicked();void on_pushButtonMid_clicked();void on_pushButtonRight_clicked();void on_pushButtonBold_clicked();void on_pushButtonSaveAs_clicked();private:Ui::QStandardItemModelDialog* ui;QStandardItemModel* model;QLabel* labCurFile;QLabel* labCellPos;QLabel* labCellText;QItemSelectionModel* theSelection;};#endif // QSTANDARDITEMMODELDIALOG_H
QStandardItemModelDialog.cpp
#include QStandardItemModelDialog.h
#include ui_QStandardItemModelDialog.h
#include QAbstractItemView
#include QFileDialog
#include QTextStreamQStandardItemModelDialog::QStandardItemModelDialog(QWidget* parent): QDialog(parent), ui(new Ui::QStandardItemModelDialog)
{ui-setupUi(this);model new QStandardItemModel(0, FixedColumnCount, this);theSelection new QItemSelectionModel(model);connect(theSelection, SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(on_currentChanged(QModelIndex, QModelIndex)));ui-tableView-setModel(model);ui-tableView-setSelectionModel(theSelection);ui-tableView-setSelectionMode(QAbstractItemView::ExtendedSelection);ui-tableView-setSelectionBehavior(QAbstractItemView::SelectItems);
}QStandardItemModelDialog::~QStandardItemModelDialog()
{delete ui;
}void QStandardItemModelDialog::initModelFromStringList(QStringList fFileContent)
{int rowCnt fFileContent.count();model-setRowCount(rowCnt);QString header fFileContent.at(0);//用一个或多个空白字符分隔 SkipEmptyParts函数会跳过任何空的部分QStringList headerList header.split(QRegExp(\\s), QString::SkipEmptyParts);model-setHorizontalHeaderLabels(headerList);QStandardItem* item;QStringList tmpList;int j;for(int i1; irowCnt; i) {QString aLinText fFileContent.at(i);tmpList aLinText.split(QRegExp(\\s), QString::SkipEmptyParts);for(j0; jFixedColumnCount-1; j) {item new QStandardItem(tmpList.at(j));model-setItem(i-1, j, item);}item new QStandardItem(headerList.at(j));item-setCheckable(true);if(tmpList.at(j) 0) {item-setCheckState(Qt::Unchecked);} else {item-setCheckState(Qt::Checked);}model-setItem(i-1, j, item);}
}void QStandardItemModelDialog::on_currentChanged(const QModelIndex current, const QModelIndex previous)
{if(current.isValid()) {// labCellPos-setText(QString::asprintf(current: row%d , col%d, current.row(), current.column()));QStandardItem* item model-itemFromIndex(current);// this-labCellText-setText(text:item-text());// QFont font item-font();}
}void QStandardItemModelDialog::on_pushButtonOpen_clicked()
{QString curPath QCoreApplication::applicationDirPath();QString aFileName QFileDialog::getOpenFileName(this, u8打开文件, curPath);if(aFileName.isEmpty()) {return;}QStringList fFileContent;QFile afile(aFileName);if(afile.open(QIODevice::ReadOnly |QIODevice::Text)) {QTextStream aStream(afile);ui-plainTextEdit-clear();while(!aStream.atEnd()) {QString str aStream.readLine();ui-plainTextEdit-appendPlainText(str);fFileContent.append(str);}afile.close();// labCurFile-setText(currentFile:aFileName);initModelFromStringList(fFileContent);}
}void QStandardItemModelDialog::on_pushButtonAdd_clicked()
{QListQStandardItem* itemList;QStandardItem* item;//不包含最后一列for(int i0; iFixedColumnCount-1; i) {item new QStandardItem(0);// item-setCheckable(true);itemListitem;}QString str model-headerData(model-columnCount()-1, Qt::Horizontal, Qt::DisplayRole).toString();item new QStandardItem(str);item-setCheckable(true);itemListitem;model-insertRow(model-rowCount(), itemList);QModelIndex curIndex model-index(model-rowCount()-1, 0);theSelection-clearSelection();theSelection-setCurrentIndex(curIndex, QItemSelectionModel::Select);
}void QStandardItemModelDialog::on_pushButtonInsert_clicked()
{QListQStandardItem* itemList;QStandardItem* item;//不包含最后一列for(int i0; iFixedColumnCount-1; i) {item new QStandardItem(0);// item-setCheckable(true);itemListitem;}QString str model-headerData(model-columnCount()-1, Qt::Horizontal, Qt::DisplayRole).toString();item new QStandardItem(str);item-setCheckable(true);itemListitem;QModelIndex curIndex theSelection-currentIndex();int curRow curIndex.row();model-insertRow(curRow, itemList);curIndex model-index(curRow, 0);theSelection-clearSelection();theSelection-setCurrentIndex(curIndex, QItemSelectionModel::Select);
}void QStandardItemModelDialog::on_pushButtonRemove_clicked()
{QModelIndex curIndex theSelection-currentIndex();if(curIndex.row() model-rowCount()-1) {model-removeRow(curIndex.row());} else {model-removeRow(curIndex.row());theSelection-setCurrentIndex(curIndex, QItemSelectionModel::Select);}
}void QStandardItemModelDialog::on_pushButtonLeft_clicked()
{if(!theSelection-hasSelection()) {return;}QModelIndexList selectedIndex theSelection-selectedIndexes();for(int i0; iselectedIndex.count(); i) {QModelIndex aIndex selectedIndex.at(i);QStandardItem* item model-itemFromIndex(aIndex);item-setTextAlignment(Qt::AlignLeft);}
}void QStandardItemModelDialog::on_pushButtonMid_clicked()
{if(!theSelection-hasSelection()) {return;}QModelIndexList selectedIndex theSelection-selectedIndexes();for(int i0; iselectedIndex.count(); i) {QModelIndex aIndex selectedIndex.at(i);QStandardItem* item model-itemFromIndex(aIndex);item-setTextAlignment(Qt::AlignCenter);}
}void QStandardItemModelDialog::on_pushButtonRight_clicked()
{if(!theSelection-hasSelection()) {return;}QModelIndexList selectedIndex theSelection-selectedIndexes();for(int i0; iselectedIndex.count(); i) {QModelIndex aIndex selectedIndex.at(i);QStandardItem* item model-itemFromIndex(aIndex);item-setTextAlignment(Qt::AlignRight);}
}void QStandardItemModelDialog::on_pushButtonBold_clicked()
{if(!theSelection-hasSelection()) {return;}QModelIndexList selectedIndex theSelection-selectedIndexes();for(int i0; iselectedIndex.count(); i) {QModelIndex aIndex selectedIndex.at(i);QStandardItem* item model-itemFromIndex(aIndex);QFont font item-font();font.setBold(Qt::Checked);item-setFont(font);}
}void QStandardItemModelDialog::on_pushButtonSaveAs_clicked()
{QString curPath QCoreApplication::applicationDirPath();QString aFileName QFileDialog::getSaveFileName(this, u8选择一个文件, curPath);if(aFileName.isEmpty()) {return;}QFile file(aFileName);if(!(file.open(QIODevice::ReadWrite | QIODevice::Text| QIODevice::Truncate))) {return;}QTextStream aStream(file);QStandardItem* item;int i, j;QString str;ui-plainTextEdit-clear();for(int i0; imodel-columnCount(); i) {item model-horizontalHeaderItem(i);str str item-text()\t\t;}aStreamstr\n;ui-plainTextEdit-appendPlainText(str);for(i0; imodel-rowCount(); i) {str;for(j0; jmodel-columnCount()-1; j) {item model-item(i, j);strstritem-text()QString::asprintf(\t\t);}item model-item(i, j);if(item-checkState() Qt::Checked) {str str1;} else {str str0;}ui-plainTextEdit-appendPlainText(str);aStreamstr\n;}
}
自定义代理
QAbstractItemDelegate是所有代理类的抽象基类QStyledItemDelegate是视图组件使用的缺省的代理类QItemDelegate也是类似功能的类。 QStyledItemDelegate和QItemDelegate的差别在于前者可以使用样式表设置来绘制组件因此建议使用QStyledItemDelegate作为自定义代理类组件的基类。 无论从QStyledItemDelegate还是QItemDelegate继承设计自定义代理组件都会必须实现这四个函数。
createEditor创建用于编辑模型数据的widget组件如QSpinBox组件setEditorData从数据模型获取数据供widget组件进行编辑setModelData将widget上的数据更新到数据模型updateEditorGeometry用于给widget组件设置一个合适的大小
详见我之前一段时间所写的文章 文章地址