Qt开发笔记之QTableWidget的使用
- 前言
- 需求
- 数据准备
- tablewidget用法
- STL map的使用
- 自定义控件的加入
- 后记
前言
QT是我唯一会用的图形库。虽然C++在图形编程方面不算主流,但是Qt在界面之外还提供了很多优秀的支持。可以说Qt更像是平台而不是一个图形库,比如它提供了自己的模板代替STL,有自己的一套多线程API和网络API,还有信号与槽机制。总的来说,Qt对于C++开发人员来说还是一个十分给力的工具。
这个系列相当于我个人开发的日记,可能质量不会很高,很多细节也不会讲,如果有兴趣了解的朋友可以留言,如果只是想学习技术请移步本文链接中其他好文章。
需求
我们今天要使用的是QTableWidget这个控件,首先介绍一下我们要实现的功能。
我们有这样一个系统,左侧是一个树形控件,右侧是一个QTableWidget控件。我们要做的是,在左侧点击某一类控件时,能在右边的QTableWidget上显示所有该类的设备。
我们的表头有四个:名称,上级名称,品牌和操作。前三项可以通过数据库查询到,而后面一项比较特殊,是一个信息按钮和一个删除按钮。
接下来看如何实现我们的需求。
数据准备
我们首先准备需要显示数据,数据从数据库中获取。关于数据库的操作我们可以看这篇博客:Qt学习之路八——利用qt对数据库进行操作。我们远程连接centos上的mysql数据库,代码如下:
1 2 3 4 5 6 7 8 9 10 11 | //打开数据库 QSqlDatabase data_base = QSqlDatabase::addDatabase("QMYSQL"); data_base.setHostName("192.168.101.162"); data_base.setPort(3306); data_base.setDatabaseName("mydb"); data_base.setUserName("root"); data_base.setPassword("password"); if (!data_base.open()) { QMessageBox::warning(this, "错误", data_base.lastError().text()); return; } |
如果没有报错我们就执行标准sql语句查数据库了:
1 2 3 4 5 6 7 8 9 10 11 12 | QString sql; if (cat == 0)//输入类别为0我们查所有数据,否则根据cat查特定class的数据 sql = QString("select * from device"); else sql = QString("select * from device where class = '%1'").arg(QString::number(cat)); QSqlQuery query; query.exec(sql); while (query.next()) { QString name = query.value(1).toString(); //... } |
在while循环中,我们实际上是一行一行地访问数据表中地内容,接下来我们看如何把这些数据显示到我们的界面上面。
tablewidget用法
关于tablewidget的用法,可以看看这篇博客:Qt QTableWidget用法总结。
我们固定显示15行,配合上交错色使界面显得更为美观,当多出15行时我们就增加行数(这个增加行数是不是必要的,我没有测试);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int rows = 0; ui.tableWidget->clearContents(); ui.tableWidget->setRowCount(15); ui.tableWidget->setFocusPolicy(Qt::NoFocus); int cat = show_cat; while (query.next()) { if(rows>=15) ui.tableWidget->setRowCount(rows+1); QString name = query.value(1).toString(); QString parent = get_parent(query.value(4).toInt()); QString brand = query.value(2).toString(); QString inf = query.value(3).toString(); QTableWidgetItem *item_name = new QTableWidgetItem(name); set_itemstyle(item_name); QTableWidgetItem* item_parent = new QTableWidgetItem(parent); set_itemstyle(item_parent); QTableWidgetItem* item_brand = new QTableWidgetItem(brand); set_itemstyle(item_brand); ui.tableWidget->setItem(rows, 0, item_name); ui.tableWidget->setItem(rows, 1, item_parent); ui.tableWidget->setItem(rows, 2, item_brand); rows++; } |
这样每次得到请求都去访问数据库,可能开销会大些。但是可以保证显示上表现的正常。
我们这里的parent是一个数字,例如11代表了视频设备下的摄像机。我们通过map建立一个转换。
STL map的使用
map是C++ STL中的一个关联容器,也就是关键字——值对的集合,在这篇博客中我们不过多将它的原理方法,只看下怎么用并编写一个函数建立int到QString的map关系。
- map的创建和搜索:
1 2 3 | map<string, string> full_name;//初始化 full_name["LeBron"] = "James";; cout << full_name.find("LeBron")->second << endl; |
如果我们要对关联容器进行值初始化就这样写:
1 2 3 4 5 6 | map<string, string> full_name = { {"Stephen","Curry"}, {"James","Harden"}, {"LeBron","James"} }; cout << full_name.find("James")->second << endl; |
那么我们就来建立我们的map:
1 2 3 4 5 6 7 8 9 | std::map<int, QString> cmap; cmap = {{11,QString::fromLocal8Bit("摄像机")},{12,QString::fromLocal8Bit("视频平台")}}; //根据int返回名字: QString VideoSuveillance::get_parent(int cat) { QString ret = cmap.find(cat)->second; return ret; } |
界面已经开始有模有样了吧。
自定义控件的加入
在列表的第四项是一个自定义控件,包含一个信息按钮和一个删除按钮。我们来看一看如何实现。
首先我们用Qt Creator画一个界面,并编译它
然后我们写一下这个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #pragma once #include "ui_ITEM.h" class Item : public QWidget { Q_OBJECT public: Item(QWidget* parent = Q_NULLPTR); private: Ui::Item ui; }; |
1 2 3 4 5 6 7 | #include "ITEM.h" Item::Item(QWidget* parent) : QWidget(parent) { ui.setupUi(this); } |
之后就可以像widget一样向table中添加了,代码如下:
1 2 | Item* it = new Item(); ui.tableWidget->setCellWidget(rows, 3,it); |
setCellWidget函数是专门向table中添加widget类的,我们来看看效果:
是不是还可以呢?
后记
今天基本完成了界面二的开发,下周把界面三搞完就基本收工啦。