接了一个私活,做完后非要加一个这个功能,自己尝试着做了一下,模块都是独立的,不会和主界面有多少关联,主界面也基本没有改动。总体上还是属于自己瞎琢磨的一个方法,可能不是非常的专业,不过总体上就是简单快捷。
需要加的这个登录系统并没有注册功能,等同于给软件加了一个密码,密码写在源码里。
这里写目录标题
1.创建一个新的ui界面
右击项目目录,选择Add New
创建新文件:
空白界面即可,我们可以自己加控件
设置名称,然后即可。
2.打开ui设计页面,拖动控件,布置界面。
然后设计如下界面:
总共拖到的控件如下:
至于页面布局,可以在ui设计界面手动设置,或者可以在logwidget.cpp
文件下代码设置,根据自己习惯定:
void LogWidget::form_init()
{
// 文件标题名
ui->label_title->setGeometry(120,25,160,25);
ui->groupBox->setGeometry(50,60,300,125);
ui->label_name->setGeometry(25,25,100,25);
ui->edit_name->setGeometry(125,25,150,25);
ui->label_pw->setGeometry(25,75,100,25);
ui->edit_pw->setGeometry(125,75,150,25);
ui->check_name->setGeometry(85,200,100,25);
ui->check_pw->setGeometry(215,200,100,25);
ui->btn_log->setGeometry(50,235,120,30);
ui->btn_clear->setGeometry(230,235,120,30);
//调整字体大小
QFont font;
font.setPointSize(16); //实际上是16的字号,但设成16却不行
font.setFamily(("wenquanyi"));
font.setBold(false);
ui->label_title->setFont(font);
font.setPointSize(12);
ui->label_name->setFont(font);
ui->label_pw->setFont(font);
}
3.如何通过登录界面登录主界面
其实前两个部分都是无关紧要的,核心部分从这里开始。
我们之前打开主界面的主函数代码一般都是:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
但我们现在要做出的效果是,先弹出登录界面,然后根据登录界面的按钮进入主界面;
我的方法是:
1.在MainWindow 对象初始化时创建登录界面对象LogWidget,并调用LogWidget对象的show方法。
2.主函数中并不调用MainWindow 对象的show()函数,而是通过信号槽机制,通过LogWidget的登录按钮发出信号,然后调用到MainWindow的show方法
3.同样通过信号槽机制,LogWidget的登录按钮发出信号之后,调用LogWidget的close()函数,实现登录主界面后的登录界面关闭。
logwidget.h
namespace Ui {
class LogWidget;
}
class LogWidget : public QWidget
{
Q_OBJECT
public:
explicit LogWidget(QWidget *parent = nullptr);
~LogWidget();
signals:
void login(); //登录主界面信号
void close_window(); //关闭登录界面信号
public slots:
void btn_clear_clicked(); //重置按钮按下后触发的事件
void btn_log_clicked(); //登录按钮按下后触发的事件
private:
Ui::LogWidget *ui;
};
logwidget.cpp
LogWidget::LogWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LogWidget)
{
ui->setupUi(this);
// connect 3个信号槽
// 触发重置按钮的信号槽连接
connect(ui->btn_clear,SIGNAL(clicked()),this,SLOT(btn_clear_clicked()));
// 触发登录按钮的信号槽连接
connect(ui->btn_log,SIGNAL(clicked()),this,SLOT(btn_log_clicked()));
// 发出信号后关闭登录窗口的信号槽连接
connect(this,SIGNAL(close_window()),this,SLOT(close()));
}
// 清理输入栏
void LogWidget::btn_clear_clicked()
{
ui->edit_pw->clear();
ui->edit_name->clear();
}
// 登录按钮触发事件
void LogWidget::btn_log_clicked()
{
// 发出登录信号
emit(login());
// 发出关闭窗口信号
emit(close_window());
}
mainwindow.h
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
// 登录界面类的对象作为指针
LogWidget * m_log;
};
#endif // MAINWINDOW_H
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 通过指针创建登录界面类的对象
m_log = new LogWidget;
// 调用登录窗口的show()函数显示登录界面
m_log->show();
// 建立信号槽,到接收到登录界面发来的login()信号后,调用主窗口的show()函数。
connect(m_log,SIGNAL(login()),this,SLOT(show()));
}
4.设置登录界面的账号和密码
这个思路根据实际需求来定,目前我的情况,只是把这些在代码里写死即可。然后获取输入框的数据,和内置密码进行比对。
其实更常规的做法,应该时设置一个账号密码的数据库,简单一点就是设置一个json文件或者txt文件,采用文件读取的方式。
namespace Ui {
class LogWidget;
}
class LogWidget : public QWidget
{
Q_OBJECT
public:
explicit LogWidget(QWidget *parent = nullptr);
~LogWidget();
signals:
void login(); //登录主界面信号
void close_window(); //关闭登录界面信号
public slots:
void btn_clear_clicked(); //重置按钮按下后触发的事件
void btn_log_clicked(); //登录按钮按下后触发的事件
private:
Ui::LogWidget *ui;
QString m_username; // 自己设定的账号
QString m_password; // 自己设定的密码
};
logwidget.cpp
修改登录按钮触发事件btn_log_clicked()
LogWidget::LogWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LogWidget)
{
ui->setupUi(this);
// connect
// 触发重置按钮的信号槽连接
connect(ui->btn_clear,SIGNAL(clicked()),this,SLOT(btn_clear_clicked()));
// 触发登录按钮的信号槽连接
connect(ui->btn_log,SIGNAL(clicked()),this,SLOT(btn_log_clicked()));
// 发出信号后关闭登录窗口的信号槽连接
connect(this,SIGNAL(close_window()),this,SLOT(close()));
ui->edit_pw->setEchoMode(QLineEdit::Password);//输入的时候就显示圆点
m_username = "wuyongwen";
m_password = "wuyongwen";
}
void LogWidget::btn_log_clicked()
{
// 从输入框获取账号
QString name = ui->edit_name->text();
// 从输入框获取密码
QString password = ui->edit_pw->text();
//账号和密码匹配正确
if (name == m_username && password == m_password)
{
emit(login());
emit(close_window());
}
else // 账号或密码错误
QMessageBox::information(this, "Warning","Username or Password is wrong !");
}
5.实现记住账号和记住密码功能
这种功能需要我们把一部分信息存储为配置文件,程序在初始化时进行读取,然后执行对应设置。
基本思路:
1.创建一个json文件
2.登录界面初始化时会读取json文件
3.根据json文件数据觉得是否自动填入账号和密码,并在多选框内自动打勾
4.每次触发登录按钮,假如成功登录,就再一次根据多选框的打勾情况,重新写入json文件。
(在本显示代码中,设置的json存取路径为当前的项目包路径(QApplication::applicationDirPath()+“/config.json”),可以自行替换json文件的路径)
json文件设置
SAVE_NAME对应键值0表示不保存账号,1表示保存账号;
SAVE_PASSWORD对应键值0表示不保存密码,1表示保存密码;
logwidget.h
#include <QWidget>
#include <QMessageBox>
#include <QJsonDocument>
#include <QFile>
#include <QDebug>
#include <QJsonObject>
#include <QByteArray>
namespace Ui {
class LogWidget;
}
class LogWidget : public QWidget
{
Q_OBJECT
public:
explicit LogWidget(QWidget *parent = nullptr);
~LogWidget();
void read_json(); //读json
void write_json();//写json
void message_init(QString flag1,QString flag2);//根据json内容决定是否填充输入框
signals:
void login(); //登录主界面信号
void close_window(); //关闭登录界面信号
public slots:
void btn_clear_clicked(); //重置按钮按下后触发的事件
void btn_log_clicked(); //登录按钮按下后触发的事件
private:
Ui::LogWidget *ui;
QString m_username;
QString m_password;
};
logwidget.cpp
#include "logwidget.h"
#include "ui_logwidget.h"
LogWidget::LogWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LogWidget)
{
ui->setupUi(this);
// connect
// 触发重置按钮的信号槽连接
connect(ui->btn_clear,SIGNAL(clicked()),this,SLOT(btn_clear_clicked()));
// 触发登录按钮的信号槽连接
connect(ui->btn_log,SIGNAL(clicked()),this,SLOT(btn_log_clicked()));
// 发出信号后关闭登录窗口的信号槽连接
connect(this,SIGNAL(close_window()),this,SLOT(close()));
ui->edit_pw->setEchoMode(QLineEdit::Password);//输入的时候就显示圆点
m_username = "wuyongwen";
m_password = "wuyongwen";
// 读取json文件
read_json();
}
void LogWidget::read_json()
{
//打开文件
QFile file(QApplication::applicationDirPath()+"/config.json");
if(!file.open(QIODevice::ReadOnly)) {
qDebug() << "File open failed!";
} else {
qDebug() <<"File open successfully!";
}
QJsonDocument jdc(QJsonDocument::fromJson(file.readAll()));
QJsonObject obj = jdc.object();
QString save_name_flag=obj.value("SAVE_NAME").toString();
QString save_password_flag=obj.value("SAVE_PASSWORD").toString();
message_init(save_name_flag,save_password_flag);
}
//根据json内容决定是否填充输入框
void LogWidget::message_init(QString flag1,QString flag2)
{
//qDebug() << flag1 << "^^^" << flag2 ;
if (flag1 == "1")
{
ui->edit_name->setText("wuyongwen");
ui->check_name->setChecked(true);
}
if(flag2 == "1")
{
ui->edit_pw->setText("wuyongwen");
ui->check_pw->setChecked(true);
}
}
// 清理输入栏
void LogWidget::btn_clear_clicked()
{
ui->edit_pw->clear();
ui->edit_name->clear();
}
//登录按钮按下后触发的事件
void LogWidget::btn_log_clicked()
{
QString name = ui->edit_name->text();
QString password = ui->edit_pw->text();
if (name == m_username && password == m_password)
{
emit(login());
write_json();
emit(close_window());
}
else
QMessageBox::information(this, "Warning","Username or Password is wrong !");
}
// 更新json文件
void LogWidget::write_json()
{
QFile file(QApplication::applicationDirPath()+"/config.json");
if(!file.open(QIODevice::WriteOnly)) {
qDebug() << "File open failed!";
} else {
qDebug() <<"File open successfully!";
}
QJsonObject obj;
bool flag = ui->check_name->isChecked();
if(flag == true)
{
obj["SAVE_NAME"] = "1";
}
else
obj["SAVE_NAME"] = "0";
flag = ui->check_pw->isChecked();
if(flag == true)
{
obj["SAVE_PASSWORD"] = "1";
}
else
obj["SAVE_PASSWORD"] = "0";
QJsonDocument jdoc(obj);
file.write(jdoc.toJson());
file.flush();
}
6. 防止主窗口和登录窗口同时打开
在main.cpp主函数中,注释掉主窗口的show()函数:
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// w.show();
return a.exec();
}
7.最终完整代码:
logwidget.h
#ifndef LOGWIDGET_H
#define LOGWIDGET_H
#include <QWidget>
#include <QMessageBox>
#include <QJsonDocument>
#include <QFile>
#include <QDebug>
#include <QJsonObject>
#include <QByteArray>
namespace Ui {
class LogWidget;
}
class LogWidget : public QWidget
{
Q_OBJECT
public:
explicit LogWidget(QWidget *parent = nullptr);
~LogWidget();
void form_init(); //格式初始化
void func_init(); //功能初始化
void read_json();
void write_json();
void message_init(QString flag1,QString flag2);
signals:
void login(); //登录主界面信号
void close_window(); //关闭登录界面信号
public slots:
void btn_clear_clicked(); //重置按钮按下后触发的事件
void btn_log_clicked(); //登录按钮按下后触发的事件
private:
Ui::LogWidget *ui;
QString m_username;
QString m_password;
};
#endif // LOGWIDGET_H
logwidget.cpp
#include "logwidget.h"
#include "ui_logwidget.h"
LogWidget::LogWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LogWidget)
{
ui->setupUi(this);
form_init();
func_init();
}
LogWidget::~LogWidget()
{
delete ui;
}
void LogWidget::form_init()
{
// 文件标题名
ui->label_title->setGeometry(120,25,160,25);
ui->groupBox->setGeometry(50,60,300,125);
ui->label_name->setGeometry(25,25,100,25);
ui->edit_name->setGeometry(125,25,150,25);
ui->label_pw->setGeometry(25,75,100,25);
ui->edit_pw->setGeometry(125,75,150,25);
ui->check_name->setGeometry(85,200,100,25);
ui->check_pw->setGeometry(215,200,100,25);
ui->btn_log->setGeometry(50,235,120,30);
ui->btn_clear->setGeometry(230,235,120,30);
//调整字体大小
QFont font;
font.setPointSize(16); //实际上是16的字号,但设成16却不行
font.setFamily(("wenquanyi"));
font.setBold(false);
ui->label_title->setFont(font);
font.setPointSize(12);
ui->label_name->setFont(font);
ui->label_pw->setFont(font);
}
void LogWidget::func_init()
{
// connect
// 触发重置按钮的信号槽连接
connect(ui->btn_clear,SIGNAL(clicked()),this,SLOT(btn_clear_clicked()));
// 触发登录按钮的信号槽连接
connect(ui->btn_log,SIGNAL(clicked()),this,SLOT(btn_log_clicked()));
// 发出信号后关闭登录窗口的信号槽连接
connect(this,SIGNAL(close_window()),this,SLOT(close()));
ui->edit_pw->setEchoMode(QLineEdit::Password);//输入的时候就显示圆点
m_username = "sazass";
m_password = "123456";
read_json();
}
// 清理输入栏
void LogWidget::btn_clear_clicked()
{
ui->edit_pw->clear();
ui->edit_name->clear();
}
void LogWidget::btn_log_clicked()
{
QString name = ui->edit_name->text();
QString password = ui->edit_pw->text();
if (name == m_username && password == m_password)
{
emit(login());
write_json();
emit(close_window());
}
else
QMessageBox::information(this, "Warning","Username or Password is wrong !");
}
void LogWidget::read_json()
{
//打开文件
QFile file(QApplication::applicationDirPath()+"/config.json");
if(!file.open(QIODevice::ReadOnly)) {
qDebug() << "File open failed!";
} else {
qDebug() <<"File open successfully!";
}
QJsonDocument jdc(QJsonDocument::fromJson(file.readAll()));
QJsonObject obj = jdc.object();
QString save_name_flag=obj.value("SAVE_NAME").toString();
QString save_password_flag=obj.value("SAVE_PASSWORD").toString();
message_init(save_name_flag,save_password_flag);
}
void LogWidget::write_json()
{
QFile file(QApplication::applicationDirPath()+"/config.json");
if(!file.open(QIODevice::WriteOnly)) {
qDebug() << "File open failed!";
} else {
qDebug() <<"File open successfully!";
}
QJsonObject obj;
bool flag = ui->check_name->isChecked();
if(flag == true)
{
obj["SAVE_NAME"] = "1";
}
else
obj["SAVE_NAME"] = "0";
flag = ui->check_pw->isChecked();
if(flag == true)
{
obj["SAVE_PASSWORD"] = "1";
}
else
obj["SAVE_PASSWORD"] = "0";
QJsonDocument jdoc(obj);
file.write(jdoc.toJson());
file.flush();
}
void LogWidget::message_init(QString flag1,QString flag2)
{
//qDebug() << flag1 << "^^^" << flag2 ;
if (flag1 == "1")
{
ui->edit_name->setText("sazass");
ui->check_name->setChecked(true);
}
if(flag2 == "1")
{
ui->edit_pw->setText("123456");
ui->check_pw->setChecked(true);
}
}
mainwindow.h(省略无关内容)
#include "logwidget.h"
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
LogWidget * m_log;
};
mainwindow.cpp(省略无关内容)
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_log = new LogWidget;
m_log->show();
// 注意,这个信号槽的作用就是激活主窗口的,我们已经让主窗口不可以自动打开,
// 必须通过登录窗口中登录按钮发出的信号槽的信号才能打开
connect(m_log,SIGNAL(login()),this,SLOT(show()));
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// 这边把主窗口的show()函数,这样主窗口就不会自动打开,
// 必须通过登录窗口发出的信号,才能启动主窗口的show()函数。
// w.show();
return a.exec();
}
8. 源码分享
链接:https://pan.baidu.com/s/1gjTUdTLz0FXSRnqQq21Xiw?pwd=ot98
提取码:ot98
–来自百度网盘超级会员V5的分享
链接:https://pan.baidu.com/s/1SyLRjsLFpYiU9M7y1ZVw7Q?pwd=yloz
提取码:yloz
–来自百度网盘超级会员V6的分享
9. 答疑
Q:用户信息的jeson文件保存到了哪里?
A:直接对照 第7部分最终完整代码给出的代码,logwidget.cpp中的write_json()写入json文件(122行)和read_json()函数读取json文件(104行),里面QFile file(json文件地址)
代码中给出的QApplication::applicationDirPath()+"/config.json"
,默认在QT项目的一级目录下,保存的json文件命名为config.json
。这里是写的是相对路径,也可以根据自己的需求进行更改,也可以修改为绝对路径。