QT模擬實現網頁登錄界面
常見的網絡登錄界面一般包括用戶名 Lable 和編輯框,密碼 Label 和編輯框,是否保存密碼的 Check 按鈕,以及確定登錄和退出按鈕組成,界面設計如下:
一般的登錄流程如下:用戶輸入用戶名和密碼,有的可能會勾選保存密碼選項;然後點擊確定按鈕向服務器發出登錄請求;服務器收到請求後與數據庫中存儲的記錄比較,存在則允許用戶登入系統;客戶端在收到確認後先將本次登錄計入存入本地文件或數據庫,然後開始加載相關內容或服務。
所以在後程序需要模擬服務器驗證和用戶輸入記錄緩存的功能。
明白基本流程後,下面介紹一下程序設計。程序界面實現類爲QLogInWindow,頭文件:
#ifndef QLOGINWINDOW_H
#define QLOGINWINDOW_H
#include <QMainWindow>
class QLineEdit;
class QPushButton;
class QCheckBox;
class QLogInWindow : public QMainWindow
{
Q_OBJECT
public:
QLogInWindow(QWidget *parent = 0);
~QLogInWindow() {}
private:
void createConnection();//初始化數據庫
bool CheckUser(const QString&, const QString&);//用戶校驗
void SaveEntrytoFile(const QString&, const QString&);//保存登錄記錄到本地
//響應事件
public slots:
void onOkButtonClicked();
void onKeyboardButtonPressed();
void onKeyboardButtonReleased();
void onPasswdChanged(const QString&);
private:
QLineEdit *user_entry;//用戶名
QLineEdit *passwd_entry;//密碼
QPushButton* m_EyeButton;//密碼顯示或隱藏按鈕
QCheckBox *rememberPSW; //是否記住密碼
};
#endif // QLOGINWINDOW_H
該類的設計遵循登錄界面的基本結構,slot 函數分別對應確定按鈕和密碼顯示控制按鈕。
實現:
#include "qloginwindow.h"
// For Debuging
#include <QDebug>
#include <QDate>
#include <QLabel>
#include <QLayout>
#include <QPushButton>
#include <QCheckBox>
#include <QLineEdit>
#include <QMessageBox>
#include <QRegExpValidator>
// For SQL
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlDriver>
QLogInWindow::QLogInWindow(QWidget *parent) : QMainWindow(parent)
{
QWidget *w = new QWidget(this);
this->setCentralWidget(w);
this->setWindowTitle("Log In Demo");
QGridLayout *grid = new QGridLayout(w);
user_entry = new QLineEdit(w);
user_entry->setPlaceholderText("User name");
passwd_entry = new QLineEdit(w);
passwd_entry->setPlaceholderText("Password");
passwd_entry->setEchoMode(QLineEdit::Password);//實現網頁登錄時的眼睛按鈕
passwd_entry->setContextMenuPolicy(Qt::NoContextMenu);//禁止右鍵菜單
//密碼顯示或隱藏提示按鈕
m_EyeButton = new QPushButton();
m_EyeButton->setObjectName("pEyeButton");
m_EyeButton->setFixedSize(QSize(16, 16));
m_EyeButton->setCursor(QCursor(Qt::PointingHandCursor));
m_EyeButton->setIcon(QIcon(":/Icon/Images/eye-close.png"));
m_EyeButton->setVisible(false);
QHBoxLayout* passwordEditLayout = new QHBoxLayout();
passwordEditLayout->addStretch();
passwordEditLayout->addWidget(m_EyeButton);
passwordEditLayout->setSpacing(0);
passwordEditLayout->setContentsMargins(0, 0, 8, 0);
passwd_entry->setLayout(passwordEditLayout);
QRegExp regx("^[^@$%#&^*|/?!~`\'\"]+$");
if(!regx.isValid()){
QString str = regx.errorString();
qDebug() << "Date:" << QDate::currentDate() <<
", Error:" << str;
}
QValidator *validator = new QRegExpValidator(regx, passwd_entry);
passwd_entry->setValidator(validator);//如何模仿 Windows 當輸入包含特殊符號時的提示功能,不能跳過
grid->addWidget(new QLabel("Username", w), 0, 0, 0);
grid->addWidget(new QLabel("Password", w), 1, 0, 0);
grid->addWidget(user_entry, 0, 1, 0);
grid->addWidget(passwd_entry, 1, 1, 0);
rememberPSW = new QCheckBox("記住密碼", w);
rememberPSW->setChecked(false);
grid->addWidget(rememberPSW, 2, 0, Qt::AlignLeft);//是否記憶密碼,未實現
QPushButton *OkButton = new QPushButton("Ok", w);
grid->addWidget(OkButton, 3, 0, Qt::AlignCenter);
QPushButton *CancleButton = new QPushButton("Cancle", w);
grid->addWidget(CancleButton, 3, 1, Qt::AlignCenter);
OkButton->setDefault(true); //設置默認 OK 按鈕選中
connect(OkButton, SIGNAL(clicked(bool)), this, SLOT(onOkButtonClicked()));
connect(CancleButton, SIGNAL(clicked(bool)), this, SLOT(close()));
connect(passwd_entry, SIGNAL(returnPressed()), this, SLOT(onOkButtonClicked()));
connect(m_EyeButton, SIGNAL(pressed()), this, SLOT(onKeyboardButtonPressed()));
connect(m_EyeButton, SIGNAL(released()), this, SLOT(onKeyboardButtonReleased()));
connect(passwd_entry, SIGNAL(textEdited(QString)), this, SLOT(onPasswdChanged(QString)));
// Init database
createConnection();
}
void QLogInWindow::createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
if (!db.open()) {
qFatal("Cannot open database");
return;
}
// We store <user,passwd> to query.
QSqlQuery query;
query.exec("create table User (name TEXT NOT NULL, passwd TEXT NOT NULL, primary key(name))");
query.exec("insert into User values('root', 'alpine')");
query.exec("insert into User values('mobile', 'cherry')");
return;
}
bool QLogInWindow::CheckUser(const QString &user, const QString &passwd)
{
QString sql = QString("select name,passwd from User where name='%1' and passwd='%2'").arg(user).arg(passwd);
qDebug() << sql;
QSqlQuery query;
bool ret = query.exec(sql);
if(!ret) {
qFatal("Failed to query database");
return false;
}
while (query.next()) {
qDebug() << "Record found:" << query.value("name").toString() << query.value("passwd").toString();
return true;
}
return false;
}
void QLogInWindow::SaveEntrytoFile(const QString &user, const QString &passwd)
{
if(rememberPSW->isChecked()) {
(void)user;
(void)passwd;
//將登陸記錄存入本地文件,未實現
}
}
void QLogInWindow::onOkButtonClicked()
{
QString user = user_entry->text();
QString passwd = passwd_entry->text();
if(CheckUser(user, passwd)) {
int ret = QMessageBox::information(this, "Welcome", "Welcome to Log in",
QMessageBox::Ok);
switch(ret) {
case QMessageBox::Ok:
SaveEntrytoFile(user, passwd);
close();
default:
break;
}
} else {
QMessageBox::warning(this, "Warnning", "User doesn't exist or wrong password",
QMessageBox::Ok);
passwd_entry->selectAll();
}
}
void QLogInWindow::onPasswdChanged(const QString &text)
{
if(text.isNull()){
m_EyeButton->setVisible(false);
} else {
m_EyeButton->setVisible(true);
}
}
void QLogInWindow::onKeyboardButtonPressed()
{
m_EyeButton->setIcon(QIcon(":/Icon/Images/eye-open.png"));
passwd_entry->setEchoMode(QLineEdit::Normal);
}
void QLogInWindow::onKeyboardButtonReleased()
{
m_EyeButton->setIcon(QIcon(":/Icon/Images/eye-close.png"));
passwd_entry->setEchoMode(QLineEdit::Password);
}
界面佈局採用 QGridLayout,界面和數據庫的初始化在該類的構造函數中完成,各個響應函數也都大部分完成,這裏用兩處沒有實現:
第一,當用戶輸入特殊字符,如“@,%,*”,我希望能像 Windows 系統那樣彈出提示框。
第二,將登錄記錄存入本地功能未實現。
另外,在添加數據庫模塊時,需要修改 pro 文件,在 pro 文件中添加如下內容:
QT += core gui sql
!contains(sql-drivers, sqlite): QTPLUGIN += qsqlite
關於密碼框的眼睛小圖標,我直接從 Windows 的登錄界面摳的圖,希望大家不要見怪。
執行效果:
程序不足之處歡迎指點。
參考鏈接:
Qt 之 模仿 QQ登陸界面——樣式篇