qt listview详细用法(listview添加多列)

「 QT 避坑指南 」远离那些躺过无数次的坑

整理 | 猿胖子

出品 | 猿武场(ID:apesarena)

QT已经封装了常用的数据库驱动,我们可以很方便对数据库操作,那么先来看看基于 SQLite 数据库操作的实例吧

qt listview详细用法(listview添加多列)

首先,完成基本的界面布局创建

在项目 pro 文件中添加 SQL 模块支持,如下

1QT =coregui 2 3#在此处添加SQL模块支持 4QT =sql 5 6greaterThan(QT_MAJOR_VERSION,4):QT =widgets 7 8CONFIG =c 11 910#YoucanmakeyourcodefailtocompileifitusesdeprecatedAPIs.11#Inordertodoso,uncommentthefollowingline.12#DEFINES =QT_DISABLE_DEPRECATED_BEFORE=0x060000#disablesalltheAPIsdeprecatedbeforeQt6.0.01314SOURCES =\15custommodel.cpp\16main.cpp\17mainwindow.cpp1819HEADERS =\20custommodel.h\21mainwindow.h

接下来,简单创建个交互界面

1/** 2*初始化UI布局 3**/ 4voidMainWindow::initUI() 5{ 6QWidget*main=newQWidget; 7this->setCentralWidget(main); 8QVBoxLayout*layout=newQVBoxLayout(main); 910QTableView*view=newQTableView;11view->setObjectName(“view”);12QHBoxLayout*menu_layout=newQHBoxLayout;13QPushButton*add_btn=newQPushButton(“新增”);14menu_layout->addWidget(add_btn);15QPushButton*modify_btn=newQPushButton(“修改”);16menu_layout->addWidget(modify_btn);17QPushButton*del_btn=newQPushButton(“删除”);18menu_layout->addWidget(del_btn);1920QVBoxLayout*content_layout=newQVBoxLayout;21QLineEdit*id_edit=newQLineEdit;22id_edit->setObjectName(“id_edit”);23id_edit->setPlaceholderText(“序号”);24id_edit->setEnabled(false);25content_layout->addWidget(id_edit);26QLineEdit*name_edit=newQLineEdit;27name_edit->setObjectName(“name_edit”);28name_edit->setPlaceholderText(“姓名”);29content_layout->addWidget(name_edit);30QLineEdit*power_edit=newQLineEdit;31power_edit->setObjectName(“power_edit”);32power_edit->setPlaceholderText(“战力”);33content_layout->addWidget(power_edit);34QLineEdit*create_edit=newQLineEdit;35create_edit->setObjectName(“create_edit”);36create_edit->setPlaceholderText(“创建时间”);37create_edit->setEnabled(false);38content_layout->addWidget(create_edit);39QLineEdit*update_edit=newQLineEdit;40update_edit->setObjectName(“update_edit”);41update_edit->setPlaceholderText(“更新时间”);42update_edit->setEnabled(false);43content_layout->addWidget(update_edit);4445layout->addLayout(menu_layout);46layout->addLayout(content_layout);47layout->addWidget(view);48}

完成这些,我们就看到运行起来的效果

添加 SQLite 数据库并创建表

我们在 mainwindow.h 中新增一个 initDB 函数,用于初始化SQLite 连接、创建用户表和插入一些默认数据

1#ifndefMAINWINDOW_H 2#defineMAINWINDOW_H 3 4#include<QMainWindow> 5#include<QSqlDatabase> 6#include<QTableView> 7 8classMainWindow:publicQMainWindow 9{10Q_OBJECT1112public:13MainWindow(QWidget*parent=nullptr);14~MainWindow();1516private:17QSqlDatabasedb;18private:19voidinitUI();20boolinitDB();

注意引用头文件QSsqlDatabase

1/** 2*初始化数据库 3*创建表并插入初始数据 4**/ 5boolMainWindow::initDB() 6{ 7boolresult=false; 8 9//创建SQLite连接10db=QSqlDatabase::addDatabase(“QSQLITE”);11//设置数据库文件路径12db.setDatabaseName(QString(“%1/apesarena.db”).arg(QDir::currentPath()));1314//打开数据库连接15db.open();16if(!exists(“tbl_users”)){17//创建用户表18QSqlQueryquery(db);19boolresult=query.exec(“CREATETABLEtbl_users(idINTEGERPRIMARYKEYAUTOINCREMENT,nameVARCHAR(20),”20″powerINT,create_dateTIMESTAMPDEFAULT(datetime(‘now’,’localtime’)),”21″update_dateTIMESTAMPDEFAULT(datetime(‘now’,’localtime’)))”);22if(!result)23returnresult;24query.clear();2526//批量插入测试数据27QVariantListval_name;28val_name<<“C”<<“C “<<“QT”;29QVariantListval_power;30val_power<<3000<<2000<<1000;3132query.prepare(“INSERTINTOtbl_usersVALUES(NULL,:name,:power,(datetime(‘now’,’localtime’)),(datetime(‘now’,’localtime’)))”);33query.bindValue(“:power”,val_power);34query.bindValue(“:name”,val_name);35result=query.execBatch();36}37returnresult;38}

注意SQLite主键自增

这里有个小坑,如果你在创建语句中主键使用的是INT而非INTEGER,那么恭喜你 SQL语句会执行成功,但主键并不会自增。这里要实现自增除了写明AUTOINCREMENT 外不能是INT 一定的写INTEGER。

1//主键ID自增2//必须是INTEGER34idINTEGERPRIMARYKEYAUTOINCREMENT56//完整创建语句7query.exec(“CREATETABLEtbl_users(idINTEGERPRIMARYKEYAUTOINCREMENT,nameVARCHAR(20),”8″powerINT,create_dateTIMESTAMPDEFAULT(datetime(‘now’,’localtime’)),”9″update_dateTIMESTAMPDEFAULT(datetime(‘now’,’localtime’)))”);

将数据从库中读取并绑定到 QTableView

我们使用QTableModel读取数据库,使用也是非常简单

1//QSqlTableModel 2 3QSqlTableModel*model=newQSqlTableModel(this,db); 4model->setEditStrategy(QSqlTableModel::OnManualSubmit); 5 6//设置访问tbl_users表 7model->setTable(“tbl_users”); 8//查询tbl_users表所以数据 9model->select();1011//model绑定到QTableView显示12findChild<QTableView*>(“view”)->setModel(model);

这就 OK 了, 在 QSqlTableModel 中呢还可以设置排序和过滤条件,调用对应的方法就可以了,非常简单易用

1//设置排序按第二列升序,参数1指定第几列,参数2升序或降序2model->setSort(1,Qt::SortOrder::AscendingOrder);34//查询power大于100的数据5model->setFilter(“power>100”);

看看程序运行结果是否符合预期

已经能顺利读取出来我们初始化时添加的数据了。但 QTableview 中的数据没有居中显示,表头也需要设置成我们所期望的代称而不是实际的字段名称。

修改表头显示,设置 View Item 内容居中

设置内容居中这个问题,目前并不能使用QSS来解决,只能通过重写QSqlTabelModel 的 data函数来实现。

1#ifndefCUSTOMMODEL_H 2#defineCUSTOMMODEL_H 3 4#include<QObject> 5#include<QSqlTableModel> 6#include<QVariant> 7#include<QSqlDatabase> 8 9classCustomModel:publicQSqlTableModel10{11Q_OBJECT12public:13explicitCustomModel(QObject*parent=nullptr,QSqlDatabasedb=QSqlDatabase());1415protected:16virtualQVariantdata(constQModelIndex&idx,introle=Qt::DisplayRole)constoverride;17signals:1819};2021#endif//CUSTOMMODEL_H

创建 CustomModel 类继承 QSqlTableModel ,重写其 data 函数,如下

1QVariantCustomModel::data(constQModelIndex&idx,introle)const 2{ 3 4//设置Model内容居中 5 6QVariantvalue=QSqlQueryModel::data(idx,role); 7if(Qt::TextAlignmentRole==role) 8value=Qt::AlignCenter; 9returnvalue;10}

在CustomMode 中新增 setHeaderLabels 函数,用于设置自定义表头

1//custommodel.h 2 3classCustomModel:publicQSqlTableModel 4{ 5Q_OBJECT 6public: 7explicitCustomModel(QObject*parent=nullptr,QSqlDatabasedb=QSqlDatabase()); 8 9//用于设置表头10voidsetHeaderLabels(constQStringList&labels);1112…1314//custommodel.cpp1516voidCustomModel::setHeaderLabels(constQStringList&labels)17{18for(inti=0;i<labels.size(); i)19setHeaderData(i,Qt::Horizontal,labels.at(i));20}2122…

完成后,我们需要在mainwindow中稍作修改,调用自定义表头设置

1//custommodel.h 2 3voidMainWindow::bindData() 4{ 5//简略部分代码… 6 7model->setTable(“tbl_users”); 8model->select(); 910//设置自定义表头11model->setHeaderLabels(QString(“序号,名讳,战力,绝技,创建时间,更新时间”).split(“,”));1213findChild<QTableView*>(“view”)->setModel(model);14}151617…

运行程序,我们将看到表头及内容居中均已按预期显示

数据库操作:新增

通过QSqlTabelModel新增一条记录保存到数据库

1voidMainWindow::addData() 2{ 3//获取用户输入 4QStringname=findChild<QLineEdit*>(“name_edit”)->text().trimmed(); 5QStringpower=findChild<QLineEdit*>(“power_edit”)->text().trimmed(); 6 7//获取当前的QSqlTableModel实例 8CustomModel*model=findChild<CustomModel*>(“cmodel”); 9QSqlRecordrecord=model->record();10record.setValue(“name”,name);11record.setValue(“power”,power);12QStringdt=QDateTime::currentDateTime().toString(“yyyy-MM-ddhh:ss:mm”);13record.setValue(“create_date”,dt);14record.setValue(“update_date”,dt);1516//新增记录17model->insertRecord(model->rowCount(),record);1819//提交修改20model->submitAll();21…2223}

数据库操作:修改

通过QSqlTabelModel修改一条记录并保存到数据库

1voidMainWindow::modifyData() 2{ 3//获取当前View选中的行 4intindex=findChild<QTableView*>(“view”)->currentIndex().row(); 5if(index<0) 6return; 7 8//获取用户修改后的数据 9QStringname=findChild<QLineEdit*>(“name_edit”)->text().trimmed();10QStringpower=findChild<QLineEdit*>(“power_edit”)->text().trimmed();11QStringcreate=findChild<QLineEdit*>(“create_edit”)->text().trimmed();1213CustomModel*model=findChild<CustomModel*>(“cmodel”);14QSqlRecordrecord=model->record(index);15record.setValue(“name”,name);16record.setValue(“power”,power);17record.setValue(“create_date”,create);18record.setValue(“update_date”,QDateTime::currentDateTime().toString(“yyyy-MM-ddhh:ss:mm”));1920model->setRecord(index,record);2122//提交变更23model->submitAll();24…

数据库操作:删除

通过QSqlTabelModel删除一条 View 中选中的记录并提交到数据库

1voidMainWindow::delData() 2{ 3CustomModel*model=findChild<CustomModel*>(“cmodel”); 4 5//删除当前View选中的行,如果未选中(row==-1)不会有变化 6model->removeRow(findChild<QTableView*>(“view”)->currentIndex().row()); 7//提交变更 8model->submitAll(); 910…

最后,给对应的按钮添加响应事件

欢迎加入程序员社群,更多技术摘要等你拿走

社群福利:

1. 行业大牛技术手札,知识点汇总;

2. 求职/招聘信息内推;

4. 人际交往,增强技术宅人际交流;

5. 调节繁杂无趣的闲暇时光;

6. 不定期线上周边於线下技术活动沙龙。

发表评论

登录后才能评论