参考:
Qt model-view 架构_w3cschool
https://www.w3cschool.cn/learnroadqt/vtxz1j4y.html
QListWidget_w3cschool
https://www.w3cschool.cn/learnroadqt/yb2k1j51.html
C++ GUI Programming with Qt 4, Second Edition
本地环境:
win10专业版,64位,Qt 5.12
目录
- item view
- QListWidget
- 效果:
- 实现
- QTableWidget
- model view
- QStringListModel
- 效果
- 实现
MVC在Qt中的实现是ModelView。其中model类似MVC中的model,但是view是view+delegate,就是对每种视图,Qt都提供了一个默认的代理。代理其实类似controller,负责渲染item和同步。
可以给一个model注册多个view,让这些view以不同的显示方式显示同一组数据,当model修改时,Qt自动同步这些view。如果数据很少,可以不用model,只用item view类,也就是QListWidget,QTableWidget,QTreeWidget,这些可以直接对item进行操作。如果数据很大,需要使用view类,如QListView,QTableView和QTreeView,同时需要提供一个model(可以是预制的也可以是自定义的)。
item view
是Qt封装好了的一些model-view类。易于使用但功能简单,同时缺少实时性支持。包括QListWidget,QTableWidget,QTreeWidget。前两个会给出实例,最后一个等用到了我再补。
QListWidget
效果:
实现
创建一个没有底部按钮的对话框,包含一个QListWidget
类型的私有变量:
QListWidget *faqListWidget;
然后修改构造函数即可:
FAQDialog::FAQDialog(QWidget *parent) :QDialog(parent),ui(new Ui::FAQDialog)
{ui->setupUi(this);// 实例化faqListWidget = new QListWidget;// sourceQStringList faqList = {tr("xxxx收费吗?"),// 若干行内容tr("您可以联系在线客服。我们非常期待您的建议,希望能给您带来更好的产品和体验。")};int listWidgetRows = faqList.length();for (int i = 0; i < listWidgetRows; i++) {if (i % 2 == 1) {// 自定义的格式,省略} else {// 如果省略第一个参数,就没有前面的icon啦QListWidgetItem* item = new QListWidgetItem(QIcon("://resources/icon/help.png"), faqList[i]);item->setTextColor(QColor("#xxxxxx"));// 如果要指定字体,使用这种方式//item->setFont(QFont("Arial", 10));QFont myfont;myfont.setBold(false);// 如果不希望修改字体,只想修改字号myfont.setPointSize(10);item->setFont(myfont);// 添加faqListWidget->addItem(item);}}// 自动换行faqListWidget->setWordWrap(true);QHBoxLayout *layout = new QHBoxLayout;layout->addWidget(faqListWidget);setLayout(layout);
}
QTableWidget
这里写过:
qt5-入门-QTableWidget简单使用-CSDN博客
https://blog.csdn.net/pxy7896/article/details/136727852
model view
- model更新的时候会自动更新view
- model一般是数据集合,可以为不同的业务建立不同的model
- Qt预定义了一些model,如
QStringListModel
、QDirModel
和QSOrtFilterProxyModel
- view大致有list、tree和table
QStringListModel
效果
有三个按钮,点击新增:
增加一个e:
删除Letter C:
点击Show展示所有数据:
实现
头文件:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QStringListModel>
#include <QListView>
#include <QWidget>namespace Ui {
class MainWindow;
}class MainWindow : public QWidget
{Q_OBJECTpublic:MainWindow();~MainWindow();private slots:void insertData();void delData();void showData();private:QStringListModel *model;QListView *listView;
};#endif // MAINWINDOW_H
源文件说明:
listView->currentIndex()
是获取QListView
当前行,但是返回值是QModelIndex
类型,这个类型保存了行、列和属于哪个model。insertRows(row, 1)
是在哪行(row),插入几次(1)model->setData(index, text);
第一个参数是QModelIndex
类型- 插入流程:先在Model中插入空白行(
insertRows(row, 1)
),然后给空白行设置内容(model->setData(index, text);
),再设置当前的index,最后设置这行是可以编辑的(listView->edit(index);
) - 如果model是空的,那么
listView->currentIndex()
的行列都是-1
#include "mainwindow.h"
//#include "ui_mainwindow.h"#include <QHBoxLayout>
#include <QPushButton>
#include <QInputDialog>
#include <QMessageBox>MainWindow::MainWindow()
{model = new QStringListModel(this);QStringList data;data << "Letter A" << "Letter B" << "Letter C";model->setStringList(data);listView = new QListView(this);listView->setModel(model);// 布局QHBoxLayout *btnLayout = new QHBoxLayout;QPushButton *insertBtn = new QPushButton(tr("insert"), this);QPushButton *delBtn = new QPushButton(tr("Delete"), this);QPushButton *showBtn = new QPushButton(tr("Show"), this);btnLayout->addWidget(insertBtn);btnLayout->addWidget(delBtn);btnLayout->addWidget(showBtn);QVBoxLayout *mainLayout = new QVBoxLayout(this);mainLayout->addWidget(listView);mainLayout->addLayout(btnLayout);this->setLayout(mainLayout);// 连接connect(insertBtn, SIGNAL(clicked()), this, SLOT(insertData()));connect(delBtn, SIGNAL(clicked()), this, SLOT(delData()));connect(showBtn, SIGNAL(clicked()), this, SLOT(showData()));
}MainWindow::~MainWindow()
{
}void MainWindow::insertData() {bool isOK;QString text = QInputDialog::getText(NULL, "Insert", "Please input new data:",QLineEdit::Normal, "You are inserting new data.",&isOK);if(isOK) { // 如果用户点击了ok按钮// 获取行int row = listView->currentIndex().row();// 第二个参数是count,1表示插入1次model->insertRows(row, 1);QModelIndex index = model->index(row);model->setData(index, text);listView->setCurrentIndex(index);// 表示可以被编辑listView->edit(index); }
}void MainWindow::delData() {if(model->rowCount() > 1) {model->removeRows(listView->currentIndex().row(), 1);}
}void MainWindow::showData() {QStringList data = model->stringList();QString str;foreach(QString s, data) {str += s + "\n";}QMessageBox::information(this, "Data", str);
}
上述的代码,如果model是空的,那么无法做插入操作,因为: listView->currentIndex().row()
此时为-1,那么model->insertRows(row, 1)
会报错。这个显然不符合逻辑。。因此注释掉data << "Letter A" << "Letter B" << "Letter C";
,修改插入和删除函数:
void MainWindow::insertData() {bool isOK;QString text = QInputDialog::getText(NULL, "Insert", "Please input new data:",QLineEdit::Normal, "You are inserting new data.",&isOK);if(isOK) {int row = listView->currentIndex().row();//qDebug() << row;QModelIndex index;// 此时model其实是空的if (row == -1) {model->insertRows(0, 1);index = model->index(0);} else {model->insertRows(row, 1);index = model->index(row);}model->setData(index, text);listView->setCurrentIndex(index);listView->edit(index);}
}void MainWindow::delData() {model->removeRows(listView->currentIndex().row(), 1);
}
done.