赞
踩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
模型和视图的主要作用就是实现数据显示和存储分离;Qt通过MVD(模型、视图、代理)实现了这种功能。
模型对数据进行封装例如封装成List、Tree、Table等,并提供了数据的访问接口,例如data()、setData()等。
有的简单的数据可以保存在Model中,复杂的可以保存在类、文件、数据库等组件中。 例如:
QStringListModel类可以保存QString数据;
QFileSystemModel类可以组织、封装文件系统数据,并提供访问接口;
QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel组织、封装数据库数据,并提供数据的访问接口。
该demo使用QTableView、QStandardItemModel、QStyledItemDelegate类创建了表格,并表格中自定义了QComboBox、QSpinBox、QPushButton、QProgressBar等,其中按钮关联槽函数,获取表格item的值并打印;并且创建了定时器,在超时槽函数中更新进度条的值。实现时,代理我选择了QStyledItemDelegate类,因为更新进度条时,需要重绘进度条样式。若只有交互组件,不用重绘组件样式,也可选用QItemDelegate。
3.1 Mainwindow.h头文件代码示例
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QTableView> #include <QStandardItemModel> #include "Myitemydelegate.h" #include <QVBoxLayout> #include <QTextBrowser> #include <QTimer> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; QString tableInitData[4][5] = {{ "张一","男","21","10","获取"},{ "张二","男","22","20","获取"}, { "张三","女","23","30","获取"},{ "张四","女","24","40","获取"}}; QTimer *updateBarTimer; QWidget *centralWidget; QTableView *tableView; QStandardItemModel *itemModel; MyItemyDelegate *delegate; QVBoxLayout *widgetVLayout; QTextBrowser *displayBrowser; void initTable(); public slots: void tableBtnClickedSlot( int row ); void updateProgressBarData(); }; #endif // MAINWINDOW_H
3.2 Mainwindow.cpp文件代码示例
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); initTable(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::initTable() { /*新建对象*/ updateBarTimer = new QTimer; centralWidget = new QWidget(this); tableView = new QTableView; itemModel = new QStandardItemModel; delegate = new MyItemyDelegate; widgetVLayout = new QVBoxLayout; displayBrowser = new QTextBrowser; /*设置表格格式*/ itemModel->setColumnCount(5); itemModel->setRowCount(4); itemModel->setHeaderData(0,Qt::Horizontal,"姓名"); itemModel->setHeaderData(1,Qt::Horizontal,"性别"); itemModel->setHeaderData(2,Qt::Horizontal,"年龄"); itemModel->setHeaderData(3,Qt::Horizontal,"学习进度"); itemModel->setHeaderData(4,Qt::Horizontal,"获取进度"); /*表格设置模型和代理*/ tableView->setModel(itemModel); tableView->setItemDelegate(delegate); /*布局*/ widgetVLayout->addWidget(tableView); widgetVLayout->addWidget(displayBrowser); centralWidget->setLayout(widgetVLayout); this->setCentralWidget(centralWidget); /*表格item初始化*/ for(int i = 0; i < 4;i++) { for(int j = 0; j < 5; j++) { itemModel->setItem(i,j,new QStandardItem(tableInitData[i][j])); itemModel->item(i,j)->setTextAlignment(Qt::AlignCenter); } } connect(delegate,SIGNAL(clicked(int)),this,SLOT(tableBtnClickedSlot(int))); connect(updateBarTimer,SIGNAL(timeout()),this,SLOT(updateProgressBarData())); updateBarTimer->start(1000); } /*表格中按钮的响应槽函数*/ void MainWindow::tableBtnClickedSlot(int row) { displayBrowser->clear(); QString itemName[4] = {"姓名:","性别:","年龄:","学习进度:"}; for(int i = 0; i < 4; i++) { displayBrowser->append(itemName[i]+itemModel->item(row,i)->text()); } } /*定时器超时函数:更新进度条*/ void MainWindow::updateProgressBarData() { for(int i = 0; i < 4; i++) { int setData = (itemModel->item(i,3)->text().toInt()+5)%100; itemModel->setData(itemModel->index(i,3),setData); } }
3.3 MyItemyDelegate.h文件代码示例
在使用代理时,有几个虚函数需要在子类中重新实现,具体可根据需要去实现,例如当需要绘制样式时,需要实现paint()函数,否则不用实现。
#ifndef MYITEMYDELEGATE_H #define MYITEMYDELEGATE_H #include <QObject> #include <QPushButton> #include <QComboBox> #include <QSpinBox> #include <QProgressBar> #include <QStyledItemDelegate> class MyItemyDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit MyItemyDelegate(QObject *parent = nullptr); ~MyItemyDelegate(); /*当需要创建自定义交互编辑器时,需要实现下面这几个函数*/ QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const override; /*当需要绘制样式时,需要重新实现paint()函数*/ void paint(QPainter* painter,const QStyleOptionViewItem &option, const QModelIndex &index) const; /*当需要过滤操作事件(例如按钮点击事件)时,需要重新实现editorEvent()函数*/ bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); signals: void clicked(int row); }; #endif // MYITEMYDELEGATE_H
3.4MyItemyDelegate.cpp文件代码示例
#include "Myitemydelegate.h" #include <QApplication> #include <QMouseEvent> #include <QDebug> MyItemyDelegate::MyItemyDelegate(QObject *parent ) :QStyledItemDelegate(parent) { } MyItemyDelegate::~MyItemyDelegate() { } QWidget * MyItemyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { if(index.column() == 1) /*性别*/ { QComboBox *tableComBox = new QComboBox(parent); tableComBox->addItem("男"); tableComBox->addItem("女"); return tableComBox; } else if(index.column() == 2) /*年龄*/ { QSpinBox *tableSpinBox = new QSpinBox(parent); tableSpinBox->setFrame(false); tableSpinBox->setMinimum(0); tableSpinBox->setMaximum(100); return tableSpinBox; } else if(index.column() == 3) /*进度*/ { return nullptr; } else if(index.column() == 4) /*控制按钮*/ { return nullptr; } return QStyledItemDelegate::createEditor(parent,option,index); } void MyItemyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if(index.column() == 1) /*性别*/ { QString value = index.model()->data(index,Qt::EditRole).toString(); QComboBox* comboBox = static_cast<QComboBox*>(editor); int tindex = comboBox->findText(value); comboBox->setCurrentIndex(tindex); } else if(index.column() == 2) /*年龄*/ { int value = index.model()->data(index,Qt::EditRole).toInt(); QSpinBox* spinBox = static_cast<QSpinBox*>(editor); spinBox->setValue(value); } else { QStyledItemDelegate::setEditorData(editor,index); } } void MyItemyDelegate::setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const { if(index.column() == 1) /*性别*/ { QComboBox* comboBox = static_cast<QComboBox*>(editor); QString text = comboBox->currentText(); model->setData(index,text,Qt::EditRole); } else if(index.column() == 2) /*年龄*/ { QSpinBox* spinBox = static_cast<QSpinBox*>(editor); spinBox->interpretText(); int value = spinBox->value(); model->setData(index,value,Qt::EditRole); } else { QStyledItemDelegate::setModelData(editor,model,index); } } void MyItemyDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index) editor->setGeometry(option.rect); } void MyItemyDelegate::paint(QPainter* painter,const QStyleOptionViewItem &option, const QModelIndex &index) const { if(index.isValid() && (index.column() == 3)) { QStyleOptionProgressBar *progressBar = new QStyleOptionProgressBar; progressBar->rect = option.rect; progressBar->progress = index.data().toInt(); progressBar->maximum = 100; progressBar->minimum = 0; progressBar->text = QString::number(progressBar->progress)+"%"; progressBar->textVisible = true; progressBar->textAlignment = Qt::AlignCenter; QApplication::style()->drawControl(QStyle::CE_ProgressBar,progressBar,painter); } else if(index.isValid() && (index.column() == 4)) { QStyleOptionButton *btnStyle = new QStyleOptionButton; btnStyle->text = "获取"; btnStyle->rect = option.rect; btnStyle->state = QStyle::State_Enabled; QPushButton btn; btn.style()->drawControl(QStyle::CE_PushButton, btnStyle, painter,&btn); } else { QStyledItemDelegate::paint(painter,option,index); } } bool MyItemyDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { Q_UNUSED(model); QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if(option.rect.contains(mouseEvent->pos())) { if((event->type() == QEvent::MouseButtonPress) && (index.column() == 4)) { emit clicked(index.row()); } } return QStyledItemDelegate::editorEvent(event, model, option, index); }
以上就是今天要讲的内容,本文以QTableView为例,仅仅简单介绍模型、视图、代理的简单使用方法;Qt还提供了其它丰富的类,感兴趣可继续深入学习。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。