Qt C++:综合数字图像处理平台–登录界面设计
如何设计一个登陆界面
网络上关于利用Qt设计登录界面的例程很多,实现的复杂度不同功能也相应有所区别。
Qt封装实现了强大的对话框功能(后面有时间专门写一章详细介绍Qt的对话框使用的文章),通常我们使用对话框来实现短期任务和用户交互。在这次的项目中采用一种简单的逻辑实现–QDialog实现。
程序运行后,首先创建一个包含QLabel(文本信息提示)、QLineEdit(用户信息处理)、QCheckBox、QPushButton等一系列功能控件的对话框,在对话框内对相应控件的数据、功能进行处理,实现登录用户的信息验证、新用户注册等功能。由于初次学习使用Qt,登录功能的设计未使用数据库信息存储等高级功能,每个例程只能注册使用一个用户,此外,用户数据的安全性无法保证(从下文的实现代码可以看到)。等后面功力深厚了再做优化吧~
界面设计
登录界面设计如上图所示,QLineEdit实现用户名、密码输入,QCheckBox对是否记住密码进行选择,QPushButton按钮实现注册与登录功能,此外,可以根据自己的需求选择登录界面的背景图。
登录界面的右上角设计为两个QToolButton,实现登录界面的最小化与关闭。由于指定了登录窗口时钟保持置顶显示,最小化按钮未启用。
登录界面各控件命名如上图所示。
代码分析
这部分详细介绍代码实现,部分分析见代码注释。
DialogLogin继承自QDialog,此部分代码为DialogLogin的初始化(构造)与析构函数。
dialoglogin.cpp
//需要用到的相关头文件
#include <QMouseEvent>
#include <QSettings>
#include <QMessageBox>
#include <QByteArray>
#include <QCryptographicHash>
#include <QBitmap>
#include <QPainter>
#include "dialoglogin.h"
#include "ui_dialoglogin.h"
//DialogLogin构造函数
DialogLogin::DialogLogin(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogLogin){
ui->setupUi(this);
this->setAttribute(Qt::WA_DeleteOnClose); //设置该窗口为关闭时删除
this->setWindowFlags(Qt::SplashScreen|Qt::WindowStaysOnTopHint); //设置为SplashScreen, 窗口无边框 窗口置顶显示
QBitmap bmp(this->size()); //创建一张与当前窗口大小一样的位图
bmp.fill(); //初始化位图 默认Qt::white
QPainter p(&bmp);
p.setPen(Qt::NoPen);
p.setBrush(Qt::black); //设置画刷颜色
p.drawRoundedRect(bmp.rect(),10,10); //在QBitmap上绘制一个带圆角的区域
setMask(bmp); //设置窗口遮罩 实现登录界面圆角效果
ui->LoginPSWD->setEchoMode(QLineEdit::Password); //设置QLineEdit LoginPSWD为密码输入模式 即输入不可见
ui->ButtLoginClose->setStyleSheet( //关闭按钮样式表
"QToolButton{background-color:transparent}" //正常状态下
"QToolButton:pressed{background-color:red}" //鼠标按下样式
"QToolButton:hover{background-color:red}"); //鼠标悬停样式
readSettings(); //读注册表 登陆参数
}
//DialogLogin 析构函数
DialogLogin::~DialogLogin(){
delete ui;
}
槽函数,注册与登录按钮功能实现
/************************************************************
*函数:on_ButtLOGIN_clicked()
*参数:无
*功能:登陆按钮的槽函数
*返回值:无
*备注:无
************************************************************/
void DialogLogin::on_ButtLOGIN_clicked(){
QString user=ui->LoginUserName->text().trimmed(); //获取输入用户名
QString pswd=ui->LoginPSWD->text().trimmed(); //获取输入密码
if ((user == m_user)&&(pswd == m_pswd)) { //检查用户名和密码是否正确
writeSettings(); //保存设置
this->accept(); //对话框 accept(),关闭对话框
}
else{
m_tryCount++; //统计错误次数
if (m_tryCount>3){ //允许连续输错3次密码
QMessageBox::critical(this, "错误", "输入错误次数太多,强行退出");
this->reject(); //退出
}
else
QMessageBox::warning(this, "错误提示", "用户名或密码错误");
}
}
/************************************************************
*函数:on_ButtLoginRegister_clicked()
*参数:无
*功能:注册按钮的槽函数
*返回值:无
*备注:无
************************************************************/
void DialogLogin::on_ButtLoginRegister_clicked(){
QString NewUser = ui->LoginUserName->text().trimmed(); //获取输入用户名
QString NewPSWD = ui->LoginPSWD->text().trimmed(); //获取输入密码
if(QString(NewUser).isEmpty()){ //检查用户名合法性 不为空即可
QMessageBox::warning(this, tr(""), tr("用户名格式错误 \r\n请重新输入! "));
}
else if(QString(NewPSWD).isEmpty()){ //检查密码合法性
QMessageBox::warning(this, tr(""), tr("密码格式错误 \r\n请重新输入! "));
}
else{ //用户名密码均无误允许注册 简单注册 只能保存一个账户 新用户会覆盖旧用户
if(QMessageBox::Yes == QMessageBox::question(this,
tr(""),
tr("新的账号密码将会覆盖旧的账户,是否创建?"),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::Yes)){
m_user = NewUser;
m_pswd = NewPSWD;
writeSettings(); //保存设置 新账户
QMessageBox::information(this, tr(""), tr("注册成功!"));
}
else{
QMessageBox::information(this, tr(""), tr("注册失败!"));
}
}
}
用户登录数据的读写与校验实现。
/************************************************************
*函数:readSettings()
*参数:无
*功能:读取存储的用户名和密码
*返回值:无
*备注:无
************************************************************/
void DialogLogin::readSettings()
{
QString organization="Shawn-Qt";//用于注册表,
QString appName="DIP_Demo";
QSettings settings(organization,appName);//创建
bool saved=settings.value("saved",false).toBool(); //读取 saved键的值
m_user=settings.value("Username","User").toString(); //读取 Username 键的值,缺省为“user”
m_pswd=settings.value("PSWD","12345").toString(); //读取PSWD
ui->LoginUserName->setText(m_user);
if(saved){ //如果之前有保存 调用 默认显示旧的账号密码
ui->LoginPSWD->setText(m_pswd);
}
ui->LoginRemb->setChecked(saved);
}
/************************************************************
*函数:writeSettings()
*参数:无
*功能:保存用户名,密码等设置
*返回值:无
*备注:无
************************************************************/
void DialogLogin::writeSettings(){
QSettings settings("WWB-Qt","DIP_Demo"); //注册表键组
settings.setValue("Username",m_user); //用户名
settings.setValue("PSWD",m_pswd); //密码
settings.setValue("saved",ui->LoginRemb->isChecked()); //记住密码选项保存
}
重载鼠标操作函数实现登录界面鼠标任意点可拖动。
/****************************************************
*函数:mousePressEvent(QMouseEvent *event)
*参数:*event 鼠标事件指针
*功能:重载鼠标点击事件函数 监测鼠标左键按下使能窗口移动
*返回值:无
*备注:该函数在鼠标点击动作下触发
****************************************************/
void DialogLogin::mousePressEvent(QMouseEvent *event){
if (event->button() == Qt::LeftButton){ //如果是左键点击
m_moving = true; //使能窗口移动
//记录下鼠标相对于窗口的位置
//event->globalPos()鼠标按下时,鼠标相对于整个屏幕位置
//pos()->this->pos()鼠标按下时,窗口相对于整个屏幕位置
m_lastPos = event->globalPos() - pos();
}
return QDialog::mousePressEvent(event);
}
/****************************************************
*函数:mouseMoveEvent(QMouseEvent *event)
*参数:*event 鼠标事件指针
*功能:重载鼠标移动事件函数 在移动使能下移动窗口位置
*返回值:无
*备注:该函数在鼠标移动动作下触发
****************************************************/
void DialogLogin::mouseMoveEvent(QMouseEvent *event){
//(event->buttons() && Qt::LeftButton)按下是左键
//鼠标移动事件需要移动窗口,窗口移动到哪里呢?就是要获取鼠标移动中,窗口在整个屏幕的坐标,然后move到这个坐标,怎么获取坐标?
//通过事件event->globalPos()知道鼠标坐标,鼠标坐标减去鼠标相对于窗口位置,就是窗口在整个屏幕的坐标
if (m_moving && (event->buttons() && Qt::LeftButton)
&& (event->globalPos()-m_lastPos).manhattanLength() > QApplication::startDragDistance()){
move(event->globalPos()-m_lastPos);
m_lastPos = event->globalPos() - pos();
}
return QDialog::mouseMoveEvent(event);
}
/****************************************************
*函数:mouseReleaseEvent(QMouseEvent *event)
*参数:*event 鼠标事件指针
*功能:重载鼠标按键释放事件函数 失能窗口移动
*返回值:无
*备注:该函数在鼠标按键释放动作下触发
****************************************************/
void DialogLogin::mouseReleaseEvent(QMouseEvent *event){
event->globalPos();
m_moving=false; //停止移动
}
小结
登录界面的制作还是很容易的,可以使用对话框(QDialog)或者直接QWidget,其实本质都是一样的,QDialog也是继承自QWidget,只是QDialog在做登录界面时界面间传递信息方便些(继承类封装了多一些函数,功能指向性强一些而已)。
能力问题,对于注册用户,仅使用了简单的注册表保存数据,安全性没有保障,且只能同时注册使用一个用户,新用户会覆盖就用户的账户密码信息。
个人认为这部分比较有意思的是界面的样式设计,相信你在写一个功能牛逼的软件时是不会给它配上一个Low Low的XP风格界面的。这里只是使用了一个简单的圆角处理,得到一个圆角的登录界面。
详细分析下这段代码,掌握了这种方式可以设计任意形状你想要的牛逼界面。
QBitmap bmp(this->size()); //创建一张与当前窗口大小一样的位图
bmp.fill(); //初始化位图 默认Qt::white
QPainter p(&bmp); //使用QPainter对QBitmap进行绘制
p.setPen(Qt::NoPen); //设置相关画图参数
p.setBrush(Qt::black); //设置画刷颜色
//配置完绘制工具 调用你需要的函数对Bitmap 绘制
p.drawRoundedRect(bmp.rect(),10,10); //在QBitmap上绘制一个带圆角的区域
setMask(bmp); //设置窗口遮罩 实现登录界面圆角效果
此处对窗口使用setMask函数,即是为窗口添加一个遮罩bmp。
遮罩图片为Black的地方显示窗口内容,White的地方为透明(不显示)。
第2行代码QBitmap.fill函数初始化位图为White。
第5行代码设置QPainter画刷为Black。
第7行代码在与窗口大小相同全为White的Bitmap上绘制了一个黑色的带圆角的区域。
执行setMask函数后便是黑色区域正常显示,其他区域透明显示,实现圆角窗口的效果。
其实这里不一定要是黑色区域,配置画刷为red、green、blue都可以,原因可以去研究setMask的实现 [呲牙]。
总的来说,你需要先绘制好一副你需要的形状的遮罩图形,使用这个图片去对窗口进行遮罩处理即可得到你要的界面。图片可以代码绘制也可以是文件的形式加载,看你需要咯~
参考例程:https://download.csdn.net/download/qq_27131611/10955676