收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
};
构造函数初始化
CDataClass::CDataClass(QObject *parent) : QObject(parent) { Worker *worker = new Worker; //定义数据处理类 worker->moveToThread(&mWorkerThread); //把数据处理类移到线程 connect(&mWorkerThread, &QThread::finished, worker, &QObject::deleteLater); //定义信号槽,把命令发送到线程里面的槽函数 connect(this, &CDataClass::operate, worker, &Worker::doWork); //定义信号槽,接收线程里面发送的结果 connect(worker, &Worker::resultReady, this, &CDataClass::handleResults); mWorkerThread.start(); //开启线程
//初始化命令处理函数映射关系
mFuncMap["checkUserPwd"] = &CDataClass::checkUserPwd;
mFuncMap["getUsersData"] = &CDataClass::getUsersData;
mFuncMap["addUsersData"] = &CDataClass::addUsersData;
mFuncMap["editUsersData"] = &CDataClass::editUsersData;
mFuncMap["getLogsData"] = &CDataClass::getLogsData;
}
##### 1.2.4.3. 创建CWorker类
CWorker是Qt类,有以下功能:
* 定义mysql操作函数
* 定义接收页面命令槽函数
* 定义发送处理结果信号,把从数据返回到页面
//定义线程里面支持的处理数据的操作 enum WORK_TYPE { WORK_DB_QUERY = 0, //数据库查询 WORK_DB_RUN //数据库更新(增、删、改) };
class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = nullptr);
void testAddData1(); //测试函数
signals: void resultReady(const RstData &rstData); //返回处理结果信号
public slots: void doWork(const int type, const QString &func, const QString &cmd); //接收页面命令槽函数
private: QSqlDatabase mDatabase; //数据库操作对象
int RunSql(const QString &sqlStr); //执行sql语句,写入接口
int RunSql(const QString &prepare, const QMap<QString, QVariant> &values);
int RunSqlColRow(const QString &sqlStr, QVector< QVector<QString> > &result); //执行sql语句,查询接口, 返回二维数组[列][行]
int RunSqlRowCol(const QString &sqlStr, QVector< QVector<QString> > &result); //执行sql语句,查询接口, 返回二维数组[行][列]
};
##### 1.2.4.4. 创建CBaseWidget类
CBaseWidget是Qt类,作为其他页面的基类,有以下功能:
* 作为其他页面的基类
* 实现组件随页面缩放
* 定义CDataClass对象,发送命令和接收处理结果
class CBaseWidget : public QWidget { Q_OBJECT public: explicit CBaseWidget(QWidget *parent = nullptr); ~CBaseWidget();
void initWidgets(QWidget \*pageWidget, bool scaleFlag = true);
void resizeWidget();
void resizeEvent(QResizeEvent \*event);
void handleCmdData(const CmdData &argcs);
void handleCmdDataList(const QVector<CmdData> &argcsList);
signals: void operateResult(const RstData &rstData);
public slots: void handleResults(const RstData &rstData);
private: QMap<QString, QRect> mWidRectMap; CDataClass *mHandle; DialogProcessBar *mDlgProcess; bool mScaleFlag; QVector mArgcsVec;
};
##### 1.2.4.5. 创建CLogin类
CBaseWidget是Qt界面设计类,继承CBaseWidget类,有以下功能:
* 用户登录页面
namespace Ui { class CLoginForm; }
class CLoginForm : public CBaseWidget { Q_OBJECT
public: explicit CLoginForm(CBaseWidget *parent = nullptr); ~CLoginForm();
private slots: void handleMainWidExit(); //退出登录槽函数 void on_pbtLogin_clicked(); //登录槽函数 void handleResults(const RstData &rstData); //接收线程处理结果槽函数
private: Ui::CLoginForm *ui;
CHomeForm \*mMainWid; //定义主窗口
};
##### 1.2.4.6. 创建CHome类
CHome是Qt界面设计类,继承CBaseWidget类,有以下功能:
* 显示菜单导航栏
* 根据菜单显示不同页面
* 退出登录
namespace Ui { class CHomeForm; }
class CHomeForm : public CBaseWidget { Q_OBJECT
public: explicit CHomeForm(CBaseWidget *parent = nullptr); ~CHomeForm();
void initMenu();
signals: void signalExit();
private slots: void on_pbtChangePwd_clicked(); void on_pushExit_clicked(); void handleResults(const RstData &rstData); void handleMenuClicked(const QModelIndex &index); void handleTimerUpdate();
private: Ui::CHomeForm *ui;
QTimer \*mTimerUpdate;
QStringList mMenuData1;
QVector<QStringList> mMenuData2;
C3DModelsForm \*m3DModels;
CQChartsForm \*mCharts;
CUsersForm \*mUsers;
CLogsForm \*mLogs;
};
构造函数初始化,初始化展示页面对象指针,析构时删除页面对象指针
CHomeForm::CHomeForm(CBaseWidget *parent) : CBaseWidget(parent), ui(new Ui::CHomeForm) { ui->setupUi(this);
m3DModels = new C3DModelsForm();
m3DModels->setParent(this->ui->frameContent);
m3DModels->hide();
mCharts = new CQChartsForm();
mCharts->setParent(this->ui->frameContent);
mCharts->hide();
mUsers = new CUsersForm();
mUsers->setParent(this->ui->frameContent);
mUsers->hide();
mLogs = new CLogsForm();
mLogs->setParent(this->ui->frameContent);
mLogs->hide();
this->initWidgets(this);
initMenu();
mTimerUpdate = new QTimer(this);
connect(mTimerUpdate, &QTimer::timeout, this, &CHomeForm::handleTimerUpdate);
mTimerUpdate->start(1000);
handleTimerUpdate();
connect(this, &CHomeForm::operateResult, this, &CHomeForm::handleResults);
}
CHomeForm::~CHomeForm() { delete ui;
if (mTimerUpdate != nullptr)
{
delete mTimerUpdate;
}
if (m3DModels != nullptr)
{
delete m3DModels;
}
if (mCharts != nullptr)
{
delete mCharts;
}
if (mUsers != nullptr)
{
delete mUsers;
}
if (mLogs != nullptr)
{
delete mLogs;
}
}
初始化菜单导航栏
void CHomeForm::initMenu() { QStandardItemModel *model = new QStandardItemModel(ui->treeViewMenu);//创建模型 ui->treeViewMenu->setModel(model);//导入模型
model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("菜单导航"));
mMenuData1 << "首页" << "业务菜单" << "系统设置";
mMenuData2.push\_back(QStringList());
mMenuData2.push\_back(QStringList() << "3D模型" << "画图展示" << "模型3");
mMenuData2.push\_back(QStringList() << "用户管理" << "系统日志");
qDebug() << mMenuData1 << mMenuData2;
for (int i = 0; i < mMenuData1.size(); ++i)
{
model->setItem(i,0,new QStandardItem(mMenuData1[i]));
for (int j = 0; j < mMenuData2[i].size(); ++j)
{
model->item(i)->appendRow(new QStandardItem(mMenuData2[i][j]));
}
}
connect(ui->treeViewMenu, &QTreeView::clicked, this, &CHomeForm::handleMenuClicked);
ui->labelTitle->setText(mMenuData1[0]);
}
页面导航跳转
void CHomeForm::handleMenuClicked(const QModelIndex &index) { QString menuName = index.data().toString(); qDebug() << "index = " << index.row() << index.parent().row() << menuName; int row = index.parent().row() == -1 ? index.row() : index.parent().row(); if (index.parent().row() == -1 && mMenuData2[row].size() > 0) { return; }
ui->labelTitle->setText(QString("%1 / %2").arg(mMenuData1[row]).arg(menuName));
if (menuName == "首页")
{
m3DModels->hidePage();
mCharts->hidePage();
mUsers->hidePage();
mLogs->hidePage();
}
else if (menuName == "3D模型")
{
m3DModels->showPage();
mCharts->hidePage();
mUsers->hidePage();
mLogs->hidePage();
}
else if (menuName == "画图展示")
{
m3DModels->hidePage();
mCharts->showPage();
mUsers->hidePage();
mLogs->hidePage();
}
else if (menuName == "模型3")
{
m3DModels->hidePage();
mCharts->hidePage();
mUsers->hidePage();
mLogs->hidePage();
}
else if (menuName == "用户管理")
{
m3DModels->hidePage();
mCharts->hidePage();
mUsers->showPage();
mLogs->hidePage();
}
else if (menuName == "系统日志")
{
m3DModels->hidePage();
mCharts->hidePage();
mUsers->hidePage();
mLogs->showPage();
}
resizeWidget(); //页面大小调整后,其他隐藏的页面大小也要调整
}
##### 1.2.4.7. 创建CQCharts类
CQCharts是Qt界面设计类,继承CBaseWidget类,该类展示Qt图表功能,项目中使用该功能需要在pro文件中增加:QT += charts
//定义画图的数据结构 typedef QPair<QPointF, QString> Data; typedef QList DataList; typedef QList DataTable;
namespace Ui { class CQChartsForm; }
class CQChartsForm : public CBaseWidget { Q_OBJECT
public: explicit CQChartsForm(CBaseWidget *parent = nullptr); ~CQChartsForm();
void showPage(); //显示页面
void hidePage(); //隐藏页面
void resizeView(); //改变图表大小
//随机生成画图数据的函数
DataTable generateRandomData(int listCount, int valueMax, int valueCount) const;
//创建柱状图
QChart \*createBarChart(int valueCount) const;
//创建折线图
QChart \*createLineChart() const;
private slots: void handleResults(const RstData &rstData); //接收线程返回数据的槽函数
private: int m_listCount; int m_valueMax; int m_valueCount; QList<QChartView *> m_charts; DataTable m_dataTable; QChartView *mLineView; //折线图 QChartView *mbarView; //柱状图
Ui::CQChartsForm \*ui;
};
##### 1.2.4.8. 创建CUsers类
CUsers是Qt界面设计类,继承CBaseWidget类,该类展示Qt表格功能,用户QTableView和自定义模型实现,用自定义模型时在pro文件中添加DEFINES += USER\_MODEL
定义QTableView数据模型
class UserTableModel : public QAbstractTableModel { Q_OBJECT
public: UserTableModel(const QStringList &hreadList, QObject *parent = nullptr) { Q_UNUSED(parent) mRoleList = hreadList; //表头数据 }
~UserTableModel() override
{
}
//重载函数,自定义模型需要定义,返回表格行数
int rowCount(const QModelIndex & = QModelIndex()) const override
{
return mRow;
}
//重载函数,自定义模型需要定义,返回表格列数
int columnCount(const QModelIndex & = QModelIndex()) const override
{
return mColumn;
}
//重载函数,自定义模型需要定义,设置表格表头
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
{
if(role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
//qDebug() << "[headerData]" << section << mRoleList.size();
if (section < mRoleList.size())
{
return mRoleList[section];
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
//重载函数,自定义模型需要定义,设置表格数据
QVariant data(const QModelIndex &index, int role) const override
{
if(!index.isValid())
{
return QVariant();
}
switch (role)
{
case Qt::TextColorRole:
return QColor(Qt::black);
case Qt::TextAlignmentRole:
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
case Qt::DisplayRole:
{
if (mResult.size() > index.row())
{
if (mResult[0].size() > index.column())
{
if (index.column() == 7) //状态
{
return mResult[index.row()][index.column()] == "1" ? "有效" : "无效";
}
else if (index.column() == 8) //编辑
{
return "编辑";
}
else if (index.column() == 9) //删除
{
return "删除";
}
else
{
return mResult[index.row()][index.column()];
}
}
}
//qDebug() << role << index.column() << index.row();
return QVariant();
}
case Qt::CheckStateRole:
{
return QVariant(); // 返回勾选框,如果返回QVariant()就没有勾选框
}
default:
return QVariant();
}
}
//自定义函数,返回表格行数据
QVector<QString> getRowData(int row)
{
if (row < 0 || row >= mResult.size())
{
QVector<QString> result(0);
return result;
}
return mResult[row];
}
//自定义函数,清除表格数据
void clear()
{
mResult.clear();
mRow = 0;
mColumn = 0;
}
signals: void signalRecvhandleResult();
public slots: void handleResults(const RstData &rstData) { emit signalRecvhandleResult(); beginResetModel(); // 开始刷新模型 if (rstData.retCode == 0) { mResult = rstData.result; mRow = mResult.size(); qDebug() << "mRow = " << mRow; mColumn = mRow > 0 ? mResult[0].size() : 0; qDebug() << "mColumn = " << mColumn;
}
else
{
clear();
}
endResetModel(); // 结束刷新模型
}
private: int mRow; int mColumn; QStringList mRoleList; QVector< QVector > mResult;
};
定义用户页面类
namespace Ui { class CUsersForm; }
class CUsersForm : public CBaseWidget { Q_OBJECT
public: explicit CUsersForm(CBaseWidget *parent = nullptr); ~CUsersForm();
void showPage(); //显示页面,发送查询数据命令
void hidePage(); //隐藏页面,清除表格数据
void setTableHead(); //设置表格表头函数
void updateTableData(const QVector< QVector<QString> > &result); //更新表格函数
private slots: void handleResults(const RstData &rstData);//接收线程处理结果槽函数 void handleEditBtnClicked(); //行编辑槽函数 void handleDelBtnClicked(); //行删除槽函数 void handleTableClicked(const QModelIndex &index); //表格单元格点击槽函数
void on\_lineEditSearch\_editingFinished();//模糊搜索槽函数
void on\_pbtAddUsers\_clicked();
private: Ui::CUsersForm *ui;
AddDialog \*mAddDlg; //编辑用户信息弹框
};
构造函数
CUsersForm::CUsersForm(CBaseWidget *parent) : CBaseWidget(parent), ui(new Ui::CUsersForm) { ui->setupUi(this); this->initWidgets(this, false); //初始化后,页面组件跟随页面缩放
setTableHead(); //设置表头
connect(this, &CLogsForm::operateResult, this, &CLogsForm::handleResults);//连接基类中的信号,获取页面命令处理结果
connect(ui->tabViewUsers, &QTableView::clicked, this, &CUsersForm::handleTableClicked);
mAddDlg = new AddDialog();
connect(mAddDlg, &AddDialog::operateResult, this, &CUsersForm::handleResults);
}
显示页面
void CUsersForm::showPage() { QVector argcsVec; int count = 1000000; for (int var = 0; var < 1; ++var) { CmdData argcs; argcs.func = "getUsersData"; argcs.params["index"] = QString::number(var*count); argcs.params["count"] = QString::number(count); argcsVec.push_back(argcs); } handleCmdDataList(argcsVec); this->show(); }
隐藏页面
void CUsersForm::hidePage() { #ifdef USER_MODEL ((UserTableModel*)(ui->tabViewUsers->model()))->clear(); #else ((QStandardItemModel*)(ui->tabViewUsers->model()))->clear(); #endif this->hide(); }
设置表头
void CUsersForm::setTableHead() { #ifdef USER_MODEL if (ui->tabViewUsers->model() == nullptr) { QStringList head; head << "序号" << "账号" << "员工姓名" << "手机号码" << "邮箱" << "部门" << "岗位" << "账号状态" << "操作" << "操作"; UserTableModel *usrTabModel = new UserTableModel(head); ui->tabViewUsers->setModel(usrTabModel); }
ui->tabViewUsers->setStyleSheet("QHeaderView::section { background:green; color:white;min-height:3em;}");
ui->tabViewUsers->setGridStyle(Qt::SolidLine);
ui->tabViewUsers->horizontalHeader()->setStretchLastSection(true);
ui->tabViewUsers->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tabViewUsers->verticalHeader()->setVisible(false);
ui->tabViewUsers->setEditTriggers(QAbstractItemView::NoEditTriggers);
#else if (ui->tabViewUsers->model() == nullptr) { QStandardItemModel* model = new QStandardItemModel(ui->tabViewUsers); ui->tabViewUsers->setModel(model); }
QStandardItemModel\* model = ((QStandardItemModel\*)ui->tabViewUsers->model());
QStringList head;
head << "序号" << "账号" << "员工姓名" << "手机号码" << "邮箱" << "部门" << "岗位" << "账号状态" << "操作" << "操作";
model->setHorizontalHeaderLabels(head);
ui->tabViewUsers->setStyleSheet("QHeaderView::section { background:green; color:white;min-height:3em;}");
ui->tabViewUsers->setGridStyle(Qt::SolidLine);
ui->tabViewUsers->horizontalHeader()->setStretchLastSection(true);
ui->tabViewUsers->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tabViewUsers->verticalHeader()->setVisible(false);
ui->tabViewUsers->setEditTriggers(QAbstractItemView::NoEditTriggers);
#endif }
显示数据
void CUsersForm::updateTableData(const QVector<QVector > &result) { #ifdef USER_MODEL UserTableModel *usrTabModel = ((UserTableModel*)(ui->tabViewUsers->model())); RstData rstData; rstData.retCode = 0; rstData.result = result; usrTabModel->handleResults(rstData); #else QStandardItemModel* model = ((QStandardItemModel*)ui->tabViewUsers->model()); setTableHead(); if (result.size() == 0) return; int start = model->rowCount(); int col = result[0].size(); int row = result.size(); QIcon iconEdit(":/new/prefix1/images/edit.png"); QIcon iconDel(":/new/prefix1/images/edit_remove.png");
for (int i = 0; i<row; ++i)
{
QList<QStandardItem\*> list;
for (int j = 0; j<col; ++j)
{
if (j == col - 3)
{
list << new QStandardItem(result[i][j] == "1" ? "有效" : "无效");
}
else if (j == col - 2)
{
list << new QStandardItem(iconEdit, "编辑");
}
else if (j == col - 1)
{
list << new QStandardItem(iconDel, "删除");
}
else
{
list << new QStandardItem(result[i][j]);
}
}
model->insertRow(i + start, list);
}
#endif }
接收线程处理数据的槽函数
void CUsersForm::handleResults(const RstData &rstData) { qDebug() << "CUsersForm::handleResults" << rstData.func << rstData.retCode << rstData.msg; if (rstData.retCode != RET_OK) { QMessageBox::warning(this, "提示", rstData.msg); return; }
if (rstData.func == "getUsersData") // 处理查询用户数据
{
qDebug() << "CUsersForm::handleResults" << rstData.result.size();
updateTableData(rstData.result);
}
else if (rstData.func == "addUsersData") // 处理增加用户数据后更新表格
{
showPage();
}
else if (rstData.func == "editUsersData")
{
QMessageBox::warning(this, "提示", rstData.msg);
mAddDlg->hide();
showPage();
}
}
使用自定义模型消耗的内存,如图:

在pro文件中注释自定义模型条件编译,#DEFINES += USER\_MODEL,重新编译运行,就可以查看用Qt标准模型QStandardItemModel花费的内存,如图:

我们对比发现:使用自定义模型消耗610MB内存,使用QStandardItemModel花费2628MB内存,相差了4.3倍,所以为追求性能,最好实现自定义模型。
##### 1.2.4.9. 创建CLogs类
CLogs是Qt界面设计类,继承CBaseWidget类,该类展示Qt表格功能,用户QTableView和QStandardItemModel实现
namespace Ui { class CLogsForm; }
class CLogsForm : public CBaseWidget { Q_OBJECT
public: explicit CLogsForm(CBaseWidget *parent = nullptr); ~CLogsForm();
void showPage(); //显示页面,发送查询数据命令
void hidePage(); //隐藏页面,清除表格数据
void setTableHead(); //设置表格表头函数
void updateTableData(const QVector< QVector<QString> > &result); //更新表格函数
private slots: void handleResults(const RstData &rstData); //接收线程处理结果槽函数
void on\_lineEditSearch\_editingFinished(); //模糊搜索槽函数
private: Ui::CLogsForm *ui;
};
构造函数初始化
CLogsForm::CLogsForm(CBaseWidget *parent) : CBaseWidget(parent), ui(new Ui::CLogsForm) { ui->setupUi(this); this->initWidgets(this, false); //初始化后,页面组件跟随页面缩放
setTableHead(); //设置表头
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新