既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
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();
}
}
使用自定义模型消耗的内存,如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200801064232280.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l5dDU5Mzg5MTkyNw==,size_16,color_FFFFFF,t_70)
在pro文件中注释自定义模型条件编译,#DEFINES += USER\_MODEL,重新编译运行,就可以查看用Qt标准模型QStandardItemModel花费的内存,如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200801064802776.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l5dDU5Mzg5MTkyNw==,size_16,color_FFFFFF,t_70)
我们对比发现:使用自定义模型消耗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);
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l5dDU5Mzg5MTkyNw==,size_16,color_FFFFFF,t_70)
我们对比发现:使用自定义模型消耗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);
[外链图片转存中...(img-xdU0ORjX-1715651360806)]
[外链图片转存中...(img-AYunI8MC-1715651360807)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**