登陆界面(二)(转)
原文转自 https://blog.csdn.net/jdh99/article/details/25774797
环境:
主机:WIN7
开发环境:Qt5.2.1
说明:
QML设计前台界面,C++后台负责逻辑
效果图:
源代码:
前台qml文件
login.qml
/********************************************************************* * 登陆界面qml文件 * (c)copyright 2014,jdh * All Right Reserved *新建日期:2014/4/29 by jdh *修改日期:2014/4/30 by jdh *修改日期:2014/5/4 by jdh *修改日期:2014/5/5 by jdh **********************************************************************/ import QtQuick 2.0 import "content" import Login_Gui 1.0 Rectangle { id: login width: 320; height: 512 SystemPalette { id: activePalette } //C++组件:用户界面 Login_Gui { id:login_gui onSig_login_result: { //关闭登陆动画 load_gif.opacity = 0 //根据登陆结果处理 switch (result) { //登陆成功 case 0: message.text = "登陆成功" message.opacity = 1 break; //无此用户名 case 1: message.text = "登陆失败:无此用户名" message.opacity = 1 break; //密码错误 case 2: message.text = "登陆失败:密码错误" message.opacity = 1 break; //达到最大登陆次数 case 3: message.text = "登陆失败:达到最大登陆次数" message.opacity = 1 break; } } } //背景图片 Image { id: background anchors { top: parent.top; bottom: parent.bottom } anchors.fill: parent source: "pics/pic1.png" fillMode: Image.PreserveAspectCrop } //消息框 Message { id: message font_size: login.height * 0.03 anchors {centerIn: parent} opacity: 0 } //登陆动画 AnimatedImage { id: load_gif; source: "pics/load.gif" anchors {horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter} z: 100 opacity: 0 } //顶栏 Item { id: top_bar width: login.width; height: login.height * 0.06 anchors.top: parent.top Text { id: title anchors { top: parent.top; horizontalCenter: parent.horizontalCenter } //text: "登陆" text: "登陆" font.bold: true font.pointSize: login.height * 0.06 * 0.4 color: "dark red" } } //空白栏 Item { id: space1 width: login.width; height: login.height * 0.1 anchors.top: top_bar.bottom } //登陆框 Rectangle { id: rect1 width: login.width * 0.8; height: login.height * 0.3 anchors { top: space1.bottom; horizontalCenter: parent.horizontalCenter } border.color: "#707070" color: "transparent" radius: 8 Row { spacing: rect1.width * 0.05 Item { width: rect1.width * 0.05; height: rect1.height } Column { spacing: rect1.height * 0.025 Item { width: rect1.width * 0.8; height: rect1.height * 0.05 } LineInput { id: txt_user_id width: rect1.width * 0.8; height: rect1.height * 0.2 font_size:height * 0.7 //anchors {horizontalCenter: rect1.horizontalCenter; top: rect1.top; topMargin: 8} hint: "请输入用户号" text:login_gui.user_id } LineInput { id: txt_password width: rect1.width * 0.8; height: rect1.height * 0.2 font_size:height * 0.7 //anchors {horizontalCenter: rect1.horizontalCenter; bottom: btn_login.top; bottomMargin: rect1.height * 0.1} hint: "请输入密码" text:login_gui.password } Row { spacing: rect1.width * 0.1 Button { id: btn_login width: rect1.width * 0.35; height: rect1.height * 0.2 //anchors { left: rect1.left; leftMargin: 28; bottom: rect1.bottom; bottomMargin: 8 } text: "登陆" onClicked: login_req() } Button { id: btn_quit width: rect1.width * 0.35; height: rect1.height * 0.2 //anchors { right: rect1.right; rightMargin: 28; bottom: rect1.bottom; bottomMargin: 8 } text: "退出" onClicked: { Qt.quit(); } } } Row { spacing: rect1.width * 0.1 CheckBox { id: check1 width: rect1.width * 0.35; height: rect1.height * 0.2 //anchors { left: rect1.left; top: rect1.bottom } caption: "记住密码" selected: login_gui.flag_remember } CheckBox { id: check2 width: rect1.width * 0.35; height: rect1.height * 0.2 //anchors { right: rect1.right; top: rect1.bottom } caption: "自动登陆" selected: login_gui.flag_auto } } } } } //android自带键处理 FocusScope { focus: true Keys.onReleased: { if (event.key == Qt.Key_Back) { console.log("qml login quit") login.sig_btn_quit() } } } //登陆请求函数 function login_req() { //判断用户名是否有效 if (txt_user_id.text == "") { message.text = "请输入用户名" message.opacity = 1 return } //判断密码是否有效 if (txt_password.text == "") { message.text = "请输入密码" message.opacity = 1 return } //显示登陆动画 load_gif.opacity = 1 //登陆请求 login_gui.user_id = txt_user_id.text login_gui.password = txt_password.text login_gui.flag_remember = check1.selected login_gui.flag_auto = check2.selected login_gui.slot_login_req() } // //信号槽绑定 // Component.onCompleted: // { // login_gui.sig_user_id_changed.connect(login_gui.slot_btn_login) // } }
后台C++代码
main.c
/********************************************************************* * 主文件 * (c)copyright 2014,jdh * All Right Reserved *新建日期:2014/1/27 by jdh *修改日期:2014/1/28 by jdh *修改日期:2014/2/4 by jdh *修改日期:2014/2/18 by jdh *修改日期:2014/2/27 by jdh *修改日期:2014/2/28 by jdh *修改日期:2014/3/1 by jdh *修改日期:2014/4/10 by jdh *修改日期:2014/5/4 by jdh **********************************************************************/ #include "world.h" #include "main_gui.h" #include "login_gui.h" #include "light_gui.h" #include "heart_beat.h" #include "net.h" #include "data_sync_center.h" #include "set_ctrl_state.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); //注册组件到QML qmlRegisterType<Login_Gui>("Login_Gui", 1, 0, "Login_Gui"); QtQuick2ApplicationViewer viewer; viewer.setMainQmlFile(QStringLiteral("qml/SH_User/login.qml")); viewer.showExpanded(); return app.exec(); }
login_gui.h
/********************************************************************* * 登陆界面模块头文件 * (c)copyright 2014,jdh * All Right Reserved *新建日期:2014/1/29 by jdh *修改日期:2014/2/1 by jdh *修改日期:2014/2/18 by jdh *修改日期:2014/3/18 by jdh *修改日期:2014/5/4 by jdh *修改日期:2014/5/5 by jdh *修改日期:2014/5/13 by jdh **********************************************************************/ #ifndef LOGIN_GUI_H #define LOGIN_GUI_H /********************************************************************* * 头文件 **********************************************************************/ #include "world.h" /********************************************************************* * 宏定义 **********************************************************************/ /********************************************************************* * 登录间隔 *单位:ms **********************************************************************/ #define INTERVAL_LOGIN 500 /********************************************************************* * 最大登录次数 **********************************************************************/ #define NUM_LOGIN 5 /********************************************************************* * 数据结构 **********************************************************************/ /********************************************************************* * 登录界面类 **********************************************************************/ class Login_Gui : public QObject { Q_OBJECT //属性:用户名 Q_PROPERTY(QString user_id READ user_id WRITE set_user_id NOTIFY sig_user_id_changed) //属性:密码 Q_PROPERTY(QString password READ password WRITE set_password NOTIFY sig_password_changed) //属性:记住密码标志 Q_PROPERTY(bool flag_remember READ flag_remember \ WRITE set_flag_remember NOTIFY sig_flag_remember_changed) //属性:自动登录标志 Q_PROPERTY(bool flag_auto READ flag_auto \ WRITE set_flag_auto NOTIFY sig_flag_auto_changed) public: /********************************************************************* * 函数 **********************************************************************/ /********************************************************************* * 初始化函数 **********************************************************************/ Login_Gui(); /********************************************************************* * 解构函数 **********************************************************************/ ~Login_Gui(); /********************************************************************* * 属性读取:用户号 **********************************************************************/ QString user_id(); /********************************************************************* * 属性写入:用户号 **********************************************************************/ void set_user_id(QString str); /********************************************************************* * 属性读取:密码 **********************************************************************/ QString password(); /********************************************************************* * 属性写入:密码 **********************************************************************/ void set_password(QString str); /********************************************************************* * 属性读取:记住密码标志 **********************************************************************/ bool flag_remember(); /********************************************************************* * 属性写入:记住密码标志 **********************************************************************/ void set_flag_remember(bool flag); /********************************************************************* * 属性读取:自动登陆标志 **********************************************************************/ bool flag_auto(); /********************************************************************* * 属性写入:自动登陆标志 **********************************************************************/ void set_flag_auto(bool flag); signals: /********************************************************************* * 属性改变信号:用户号 **********************************************************************/ void sig_user_id_changed(); /********************************************************************* * 属性改变信号:密码 **********************************************************************/ void sig_password_changed(); /********************************************************************* * 属性改变信号:记住密码标志 **********************************************************************/ void sig_flag_remember_changed(); /********************************************************************* * 属性改变信号:自动登陆标志 **********************************************************************/ void sig_flag_auto_changed(); /********************************************************************* * 信号:登陆结果 *参数:result:0:成功 * 1:无此用户名 * 2:密码错误 * 3:达到登陆的最大次数 **********************************************************************/ void sig_login_result(int result); /********************************************************************* * 发送网络帧 *参数:id:用户名 * password:密码 * cmd:帧命令 * index:发送序列号 * frame:发送的报文 **********************************************************************/ void sig_net_tx_frame_with_id(uint32_t id,uint32_t password,int cmd,uint16_t index,QByteArray frame); public slots: /********************************************************************* * 槽函数:登陆请求 **********************************************************************/ void slot_login_req(); /********************************************************************* * 槽函数:登陆响应 *参数:data:接收的数据 **********************************************************************/ void slot_login_ack(QByteArray data); private slots: /********************************************************************* * 槽函数:心跳滴答函数 *说明:1滴答触发1次 **********************************************************************/ void slot_tick(); private: /********************************************************************* * 变量 **********************************************************************/ /********************************************************************* * 属性:用户号 **********************************************************************/ QString _user_id; /********************************************************************* * 属性:密码 **********************************************************************/ QString _password; /********************************************************************* * 属性:记住密码标志 **********************************************************************/ bool _flag_remember; /********************************************************************* * 属性:自动登录标志 **********************************************************************/ bool _flag_auto; /********************************************************************* * 滴答定时器 **********************************************************************/ QTimer *timer; /********************************************************************* * 登录计数器 **********************************************************************/ int Login_Counter; }; #endif // LOGIN_GUI_H
login_gui.c
/********************************************************************* * 登陆界面模块主文件 * (c)copyright 2014,jdh * All Right Reserved *新建日期:2014/1/29 by jdh *修改日期:2014/2/1 by jdh *修改日期:2014/2/17 by jdh *修改日期:2014/2/18 by jdh *修改日期:2014/2/16 by jdh *修改日期:2014/5/4 by jdh *修改日期:2014/5/5 by jdh *修改日期:2014/5/13 by jdh **********************************************************************/ /********************************************************************* * 头文件 **********************************************************************/ #include "login_gui.h" /********************************************************************* * 函数 **********************************************************************/ /********************************************************************* * 初始化函数 **********************************************************************/ Login_Gui::Login_Gui() { //初始化变量 Login_Counter = 0; //滴答初始化 timer = new QTimer(this); //绑定信号槽 connect(timer, SIGNAL (timeout()), this , SLOT(slot_tick())); QFile file_cfg("cfg.txt"); QByteArray arr; bool ok; int flag_remember = 0; int flag_auto_login = 0; int id = 0; int password = 0; QString str; int i = 0; int j = 0; //属性初始化 _user_id = ""; _password = ""; _flag_remember = false; _flag_auto = false; //判断文件是否存在 if (!file_cfg.exists()) { file_cfg.close(); } else { //文件存在 file_cfg.open(QIODevice::ReadOnly); //读取文件 do { str.clear(); arr = file_cfg.readLine(); for (i = 0;i < arr.count();i++) { if ((arr.at(i) >= '0' && arr.at(i) <= '9') || \ (arr.at(i) >= 'a' && arr.at(i) <= 'f') || \ arr.at(i) == 'x') { str[j++] = arr.at(i); } } flag_remember = str.toInt(&ok,16); if (!ok) { break; } str.clear(); arr = file_cfg.readLine(); for (i = 0;i < arr.count();i++) { if ((arr.at(i) >= '0' && arr.at(i) <= '9') || \ (arr.at(i) >= 'a' && arr.at(i) <= 'f') || \ arr.at(i) == 'x') { str[j++] = arr.at(i); } } flag_auto_login = str.toInt(&ok,16); if (!ok) { break; } str.clear(); arr = file_cfg.readLine(); for (i = 0;i < arr.count();i++) { if ((arr.at(i) >= '0' && arr.at(i) <= '9') || \ (arr.at(i) >= 'a' && arr.at(i) <= 'f') || \ arr.at(i) == 'x') { str[j++] = arr.at(i); } } id = str.toInt(&ok,16); if (!ok) { break; } str.clear(); arr = file_cfg.readLine(); for (i = 0;i < arr.count();i++) { if ((arr.at(i) >= '0' && arr.at(i) <= '9') || \ (arr.at(i) >= 'a' && arr.at(i) <= 'f') || \ arr.at(i) == 'x') { str[j++] = arr.at(i); } } password = str.toInt(&ok,16); if (!ok) { break; } //判断是否记住密码 if (flag_remember == VALID_FLAG) { _user_id = QString::number(id,10); _password = QString::number(password,10); _flag_remember = true; //判断是否自动登录 if (flag_auto_login == VALID_FLAG) { _flag_auto = true; slot_login_req(); } } } while (0); file_cfg.close(); } } /********************************************************************* * 解构函数 **********************************************************************/ Login_Gui::~Login_Gui() { } /********************************************************************* * 属性读取:用户号 **********************************************************************/ QString Login_Gui::user_id() { return _user_id; } /********************************************************************* * 属性写入:用户号 **********************************************************************/ void Login_Gui::set_user_id(QString str) { if (_user_id != str) { _user_id = str; emit sig_user_id_changed(); } } /********************************************************************* * 属性读取:密码 **********************************************************************/ QString Login_Gui::password() { return _password; } /********************************************************************* * 属性写入:密码 **********************************************************************/ void Login_Gui::set_password(QString str) { if (_password != str) { _password = str; emit sig_password_changed(); } } /********************************************************************* * 属性读取:记住密码标志 **********************************************************************/ bool Login_Gui::flag_remember() { return _flag_remember; } /********************************************************************* * 属性写入:记住密码标志 **********************************************************************/ void Login_Gui::set_flag_remember(bool flag) { if (_flag_remember != flag) { _flag_remember = flag; emit sig_flag_remember_changed(); } } /********************************************************************* * 属性读取:自动登陆标志 **********************************************************************/ bool Login_Gui::flag_auto() { return _flag_auto; } /********************************************************************* * 属性写入:自动登陆标志 **********************************************************************/ void Login_Gui::set_flag_auto(bool flag) { if (_flag_auto != flag) { _flag_auto = flag; emit sig_flag_auto_changed(); } } /********************************************************************* * 槽函数:登陆请求 **********************************************************************/ void Login_Gui::slot_login_req() { //初始化计数器 Login_Counter = 0; //开始尝试登陆 timer->start(INTERVAL_LOGIN); slot_tick(); } /********************************************************************* * 槽函数:登陆响应 *参数:data:接收的数据 **********************************************************************/ void Login_Gui::slot_login_ack(QByteArray data) { uint32_t id = 0; uint32_t password = 0; int flag_remember = 0; int flag_auto_login = 0; uint8_t result = 0; bool ok; #ifdef DEBUG qDebug() << "接收帧:尝试登陆" << (uint8_t)data[0] << (uint8_t)data[1] << (uint8_t)data[2]; #endif //清除计数器 Login_Counter = 0; //停止登录尝试 timer->stop(); //判断用户号和密码是否匹配 id = ((uint8_t)data[6] << 24) +\ ((uint8_t)data[7] << 16) + \ ((uint8_t)data[8] << 8) + \ (uint8_t)data[9]; password = ((uint8_t)data[10] << 24) +\ ((uint8_t)data[11] << 16) + \ ((uint8_t)data[12] << 8) + \ (uint8_t)data[13]; //登陆结果 result = (uint8_t)data[LEN_FRAME_HEAD]; //判断登陆结果 switch (result) { //登陆成功 case 0: { //判断用户名和密码是否正确 if (id == (uint32_t)_user_id.toInt(&ok) && password == (uint32_t)_password.toInt(&ok)) { //发送登陆成功信号 emit sig_login_result(0); #ifdef DEBUG qDebug() << "登陆成功" << "用户号" << _user_id << "密码" << _password; #endif //判断是否勾选记住密码以及自动登录 if (_flag_remember) { flag_remember = VALID_FLAG; } if (_flag_auto) { flag_auto_login = VALID_FLAG; } //将用户名密码保存 QFile file_cfg("cfg.txt"); file_cfg.open(QIODevice::WriteOnly); QTextStream out(&file_cfg); out << QString::number(flag_remember,16) << "\r\n" \ << QString::number(flag_auto_login,16) << "\r\n" \ << _user_id << "\r\n" \ << _password << "\r\n"; file_cfg.close(); } break; } //无此用户名 case 1: { #ifdef DEBUG qDebug() << "登陆失败" << "用户号不存在"; #endif //发送登录失败信号 emit sig_login_result(1); break; } //密码错误 case 2: { #ifdef DEBUG qDebug() << "登陆失败" << "密码错误"; #endif //发送登录失败信号 emit sig_login_result(2); break; } } } /********************************************************************* * 槽函数:心跳滴答函数 *说明:1滴答触发1次 **********************************************************************/ void Login_Gui::slot_tick() { QByteArray frame; bool ok; //登录计数器 Login_Counter++; if (Login_Counter > NUM_LOGIN) { #ifdef DEBUG qDebug() << "登录失败" << "达到最大尝试登陆次数:" << NUM_LOGIN; #endif //清除计数器 Login_Counter = 0; //停止登陆尝试 timer->stop(); //发送登陆失败信号 emit sig_login_result(3); return; } //发送登陆请求 //报文 frame.clear(); //发送网络帧 #ifdef DEBUG qDebug() << "发送帧:发送登陆请求"; #endif emit sig_net_tx_frame_with_id((uint32_t)_user_id.toInt(&ok),(uint32_t)_password.toInt(&ok),\ CMD_USER_LOGIN_REQUEST,0,frame); }
注意:该Demo不完整,缺少很多文件,无法编译成功。