本实例演示如下的一些功能的实现方法
- 如何实现Splash特点的无边框对话框
- 如何设计用鼠标拖动无边框的对话框
- 如何使用QSetteings类存储用户名,密码等信息
- 如何用QCryptographicHash类进行字符串加密
- 如何根据登陆输入状况确定启动主窗口或终止程序运行
对话框界面设计和类定义
创建启动登陆对话框,从QDialog继承而来,里设置类名为QDlgLogin。界面在UI设计器里进行,主要区域事一个用于显示图片的QLabel组件,在资源文件里载入图片,为QLabel组件的pixmap指定图片。
对话框下方事用于用户名输入的QLineEdit组件,两个按钮用于选择用户输入,设置“取消”按钮的clicked()信号与与对话框的reject()槽函数关联。
下面是qdlglogin.h文件中QDlgLogin类的定义
class QDlgLogin : public QDialog
{
Q_OBJECT
public:
explicit QDlgLogin(QWidget *parent = nullptr);
~QDlgLogin();
protected:
void mousePressEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent * event);
private slots:
void on_btnOK_clicked();
private:
Ui::QDlgLogin *ui;
bool m_moving = false; //表示窗口是否在鼠标操作下移动
QPoint m_lastPos; //上一次鼠标位置
QString m_user = "user";
QString m_pwd = "12345";
int m_tryCount = 0; //试错次数
void readSettings(); //读取设置注册表
void writeSettings(); //写入设置注册表
QString encrypt(const QString & str); //字符串加密
};
类的实现
QDlgLogin::QDlgLogin(QWidget *parent) :
QDialog(parent),
ui(new Ui::QDlgLogin)
{
ui->setupUi(this);
ui->editPSWD->setEchoMode(QLineEdit::Password);
this->setAttribute(Qt::WA_DeleteOnClose); //设置为关闭时删除
this->setWindowFlags(Qt::SplashScreen); //设置为SPlashScreen
this->setWindowFlags(Qt::FramelessWindowHint); //无边框,但在任务栏显示标题
readSettings(); //读取用户存储的用户名和密码
setMouseTracking(true);
}
QDlgLogin::~QDlgLogin()
{
delete ui;
}
void QDlgLogin::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_moving = true;
m_lastPos = event->globalPos() - pos(); //记录下鼠标相对于窗口的位置
}
return QDialog::mousePressEvent(event);
}
void QDlgLogin::mouseMoveEvent(QMouseEvent *event)
{
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);
}
void QDlgLogin::mouseReleaseEvent(QMouseEvent *event)
{
m_moving = false;
}
void QDlgLogin::readSettings()
{
QString organization="WWB-Qt"; //用于注册表
QString appName = "samp6_5";
QSettings settings(organization, appName);
bool saved = settings.value("saved", false).toBool(); //读取saved
m_user = settings.value("Username", "user").toString(); //读取Username
QString defaultPSWD = encrypt("12345"); //缺省密码“12345”加密后的数据
m_pwd = settings.value("PSWD", defaultPSWD).toString(); //读取PSWD
if (saved)
ui->editUser->setText(m_user);
ui->chkBoxSave->setChecked(saved);
}
void QDlgLogin::writeSettings()
{
QSettings settings("WWB-Qt", "samp6_5"); //注册表键组
settings.setValue("Username", m_user);
settings.setValue("PSWD", m_pwd);
settings.setValue("saved", ui->chkBoxSave->isChecked());
}
QString QDlgLogin::encrypt(const QString &str)
{
QByteArray btArray;
btArray.append(str);
QCryptographicHash hash(QCryptographicHash::Md5);
hash.addData((btArray)); //添加数据
QByteArray resultArray = hash.result(); //返回最终的散列值
QString md5 = resultArray.toHex(); //转为16进制字符串
return md5;
}
void QDlgLogin::on_btnOK_clicked()
{
QString user = ui->editUser->text().trimmed();
QString pswd = ui->editPSWD->text().trimmed();
QString encrptPSWD = encrypt(pswd); //加密密码
if ((user == m_user) && (encrptPSWD == m_pwd))
{
writeSettings();
this->accept(); //对话框accept();关闭对话框
}
else {
m_tryCount++;
if (m_tryCount > 3)
{
QMessageBox::critical(this, "错误", "输入错误次数太多,强行退出");
this->reject();
}
else {
QMessageBox::warning(this, "错误提示", "用户名或密码错误");
}
}
}
QlineEdit::setEchoMode()函数设置编辑框回显方式,参数为QLineEdit::EchoMode枚举类型。
使用setWindowFlag()函数将窗口标志设置为Qt::SplashScreen,这样对话框显示为Splash窗口,无边框,且在Windows任务栏上没有显示。另一个类似的标志是Qt::FramelessWindowHit,他会使对话框无边框,但是会在任务栏上显示对话框的标题。
应用程序的设置是指应用程序需要保存的一些信息,在windows系统下,这些信息保存在注册表里。使用QSettings类可以实现设置信息的读取和写入。创建QSettings对象时,需要传递organization和appName,例如:
QSettings settings("WWWB-Qt", "samp6_5");
指向的注册表目录是HKEY_CURRENT_USER/Software/WWB_Qt/samp6_5。
注册表里参数是以“键-键值”对来保存的,使用setValue()写入键值,value()读取键值,可以指定缺省值。
Qt提供了用于加密的类QCryptographicHash.
Splash登陆窗口的使用
设计好启动与登陆窗口QDlgLogin之后,在main()函数里使用