QTableWidget的使用
前言
QT是我唯一会用的图形库。虽然C++在图形编程方面不算主流,但是Qt在界面之外还提供了很多优秀的支持。可以说Qt更像是平台而不是一个图形库,比如它提供了自己的模板代替STL,有自己的一套多线程API和网络API,还有信号与槽机制。总的来说,Qt对于C++开发人员来说还是一个十分给力的工具。
这个系列相当于我个人开发的日记,可能质量不会很高,很多细节也不会讲,如果有兴趣了解的朋友可以留言,如果只是想学习技术请移步本文链接中其他好文章。
需求
我们今天要使用的是QTableWidget这个控件,首先介绍一下我们要实现的功能。
我们有这样一个系统,左侧是一个树形控件,右侧是一个QTableWidget控件。我们要做的是,在左侧点击某一类控件时,能在右边的QTableWidget上显示所有该类的设备。
我们的表头有四个:名称,上级名称,品牌和操作。前三项可以通过数据库查询到,而后面一项比较特殊,是一个信息按钮和一个删除按钮。
接下来看如何实现我们的需求。
数据准备
我们首先准备需要显示数据,数据从数据库中获取。关于数据库的操作我们可以看这篇博客:Qt学习之路八——利用qt对数据库进行操作。我们远程连接centos上的mysql数据库,代码如下:
//打开数据库
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语句查数据库了:
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行时我们就增加行数(这个增加行数是不是必要的,我没有测试);
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的创建和搜索:
map<string, string> full_name;//初始化
full_name["LeBron"] = "James";;
cout << full_name.find("LeBron")->second << endl;
如果我们要对关联容器进行值初始化就这样写:
map<string, string> full_name = {
{"Stephen","Curry"},
{"James","Harden"},
{"LeBron","James"}
};
cout << full_name.find("James")->second << endl;
那么我们就来建立我们的map:
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画一个界面,并编译它
然后我们写一下这个类:
#pragma once
#include "ui_ITEM.h"
class Item
: public QWidget
{
Q_OBJECT
public:
Item(QWidget* parent = Q_NULLPTR);
private:
Ui::Item ui;
};
#include "ITEM.h"
Item::Item(QWidget* parent)
: QWidget(parent)
{
ui.setupUi(this);
}
之后就可以像widget一样向table中添加了,代码如下:
Item* it = new Item();
ui.tableWidget->setCellWidget(rows, 3,it);
setCellWidget函数是专门向table中添加widget类的,我们来看看效果:
是不是还可以呢?
后记
今天基本完成了界面二的开发,下周把界面三搞完就基本收工啦。