本文共 8608 字,大约阅读时间需要 28 分钟。
系统通过虚拟键盘实现密码输入功能。当用户点击“密码输入栏”,弹出虚拟键盘,输入锁屏密码后,点击虚拟键盘外部区域,虚拟键盘将隐藏。再次点击登录按钮,用户即可成功进入主界面。
虚拟键盘采用C++和Qt框架开发,支持单例模式,确保程序中只存在一个输入法实例对象。以下是相关实现细节:
#ifndef FRMNUM_H#define FRMNUM_H#include#include #include #include #include namespace Ui { class frmNum;}class frmNum : public QWidget { Q_OBJECTpublic: explicit frmNum(QWidget *parent = nullptr); ~frmNum(); static frmNum *Instance(); void Init(QString style, int fontSize); bool eventFilter(QObject *obj, QEvent *event);protected: bool focusChanged(QWidget *oldWidget, QWidget *nowWidget);private: Ui::frmNum *ui; static frmNum *_instance; bool isPressBackBtn; bool isFirst; QPushButton *btnPress; QTimer *backBtnTimert; QWidget *currentWidget; QLineEdit *currentLineEdit; QString currentEditType; QString currentStyle; int currentFontSize; bool checkPress(); void ChangeStyle(QString currentStyle); void insertValue(QString value); void deleteValue(); void clearValue();};#endif // FRMNUM_H
#include "frmnum.h"#include "ui_frmnum.h"#include#include namespace Ui { class frmNum;}frmNum *frmNum::_instance = nullptr;frmNum::frmNum(QWidget *parent) : QWidget(parent) { ui = new Ui::frmNum; ui->setupUi(this); Init("black", 20); ui->btnClear->setFocus(); ui->btnClear->setShortcut(QKeySequence::InsertParagraphSeparator); ui->btnClear->setShortcut(Qt::Key_Enter); ui->btnClear->setShortcut(Qt::Key_Return);}~frmNum() { delete ui;}void frmNum::Init(QString style, int fontSize) { this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); isFirst = true; isPressBackBtn = false; backBtnTimert = new QTimer(this); connect(backBtnTimert, SIGNAL(timeout()), this, SLOT(reClicked())); currentWidget = nullptr; this->currentFontSize = fontSize; ChangeStyle(style); ui->btn0->setProperty("btnNum", true); ui->btn1->setProperty("btnNum", true); ui->btn2->setProperty("btnNum", true); ui->btn3->setProperty("btnNum", true); ui->btn4->setProperty("btnNum", true); ui->btn5->setProperty("btnNum", true); ui->btn6->setProperty("btnNum", true); ui->btn7->setProperty("btnNum", true); ui->btn8->setProperty("btnNum", true); ui->btn9->setProperty("btnNum", true); ui->btnDelete->setProperty("btnOther", true); QList btnList = this->findChildren (); foreach (QPushButton *btn, btnList) { connect(btn, SIGNAL(clicked()), this, SLOT(btn_clicked())); } connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)), this, SLOT(focusChanged(QWidget *, QWidget *))); qApp->installEventFilter(this);}void frmNum::focusChanged(QWidget *oldWidget, QWidget *nowWidget) { if (nowWidget != nullptr && !this->isAncestorOf(nowWidget)) { if (oldWidget == nullptr && !isFirst) { return; } isFirst = false; if (nowWidget->inherits("QLineEdit")) { currentLineEdit = dynamic_cast (nowWidget); currentEditType = "QLineEdit"; this->setVisible(true); } else { currentWidget = nullptr; currentLineEdit = nullptr; currentEditType = ""; this->setVisible(false); } QRect rect = nowWidget->rect(); QPoint pos = nowWidget->mapToGlobal(rect.left(), rect.bottom() + 2); this->setGeometry(pos.x(), pos.y(), this->width(), this->height()); } Q_UNUSED(oldWidget);}bool frmNum::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseButtonPress) { if (currentEditType == "QLineEdit") { if (obj != ui->btnClear) { this->setVisible(true); } btnPress = dynamic_cast (obj); if (checkPress()) { isPressBackBtn = true; backBtnTimert->start(500); } } return false; } else if (event->type() == QEvent::MouseButtonRelease) { btnPress = dynamic_cast (obj); if (checkPress()) { isPressBackBtn = false; backBtnTimert->stop(); } return false; } return QWidget::eventFilter(obj, event); } bool frmNum::checkPress() { return btnPress->property("btnNum").toBool() || btnPress->property("btnOther").toBool(); } void frmNum::reClicked() { if (isPressBackBtn) { backBtnTimert->setInterval(30); btnPress->click(); } } void frmNum::btn_clicked() { if (currentEditType == "") { return; } QPushButton *btn = dynamic_cast (sender()); QString objectName = btn->objectName(); if (objectName == "btnDelete") { deleteValue(); } else if (objectName == "btnClear") { clearValue(); } else { QString value = btn->text(); insertValue(value); } } void frmNum::insertValue(QString value) { if (currentEditType == "QLineEdit") { currentLineEdit->insert(value); } } void frmNum::deleteValue() { if (currentEditType == "QLineEdit") { currentLineEdit->backspace(); } } void frmNum::clearValue() { if (currentEditType == "QLineEdit") { currentLineEdit->clear(); } } void frmNum::ChangeStyle(QString currentStyle) { if (currentStyle == "blue") { changeStyle("#DEF0FE", "#C0DEF6", "#C0DCF2", "#386487"); } else if (currentStyle == "gray") { changeStyle("#E4E4E4", "#A2A2A2", "#A9A9A9", "#000000"); } else if (currentStyle == "lightgray") { changeStyle("#EEEEEE", "#E5E5E5", "#D4D0C8", "#6F6F6F"); } else { changeStyle("#4D4D4D", "#292929", "#D9D9D9", "#CACAD0"); } } void frmNum::changeStyle(QString topColor, QString bottomColor, QString borderColor, QString textColor) { QStringList qss; qss.append(QString("QWidget#frmNum{background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 %1,stop:1 %2);}") .arg(topColor).arg(bottomColor)); qss.append("QPushButton{padding:5px;border-radius:3px;}"); qss.append(QString("QPushButton:hover{background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 %1,stop:1 %2;}") .arg(topColor).arg(bottomColor)); qss.append(QString("QLabel,QPushButton{font-size:%1pt;color:%2;}") .arg(currentFontSize).arg(textColor)); qss.append(QString("QPushButton#btnPre,QPushButton#btnNext,QPushButton#btnClose{padding:5px;}"); qss.append(QString("QPushButton{border:1px solid %1;}") .arg(borderColor)); qss.append(QString("QLineEdit{border:1px solid %1;border-radius:5px;padding:2px;background:none;selection-background-color:%2;selection-color:%3;}") .arg(borderColor).arg(bottomColor).arg(topColor)); this->setStyleSheet(qss.join("")); }
虚拟键盘界面由多个按钮组成,支持数字输入和特殊功能键,美观且易于使用。
锁屏界面采用QDialog实现,以下是相关实现细节:
#ifndef LOCKWIN_H#define LOCKWIN_H#include#include #include #include <_frmnum.h>#define PASSWD "123456"namespace Ui { class LoginWin;}class LockWin : public QDialog { Q_OBJECTpublic: explicit LockWin(QWidget *parent = nullptr); ~LockWin();private: Ui::LoginWin *ui; bool eventFilter(QObject *watched, QEvent *event); frmNum *myFrmnum;};#endif // LOCKWIN_H
#include "lockWin.h"#include "ui_loginwin.h"LockWin::LockWin(QWidget *parent) : QDialog(parent) { ui = new Ui::LoginWin; ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); this->setWindowModality(Qt::WindowModal); ui->lineEdit->installEventFilter(this); QValidator *accountValidator = new QRegExpValidator(QRegExp("[0-9]{6}")); ui->lineEdit->setValidator(accountValidator); myFrmnum = new frmNum(this);}~LockWin() { delete ui;}bool LockWin::eventFilter(QObject *watched, QEvent *event) { if (watched == ui->lineEdit) { if (event->type() == QEvent::FocusIn) { if (ui->lineEdit->echoMode() == QLineEdit::Normal) { ui->lineEdit->clear(); } ui->lineEdit->setEchoMode(QLineEdit::Password); } } return QWidget::eventFilter(watched, event);}void LockWin::on_cancelButton_clicked() { ui->lineEdit->clear();}void LockWin::on_loginButton_clicked() { if (ui->lineEdit->text() == PASSWD) { this->close(); } else if (ui->lineEdit->text().isEmpty()) { ui->infoLabel->setText("输入密码不能为空!"); } else if (ui->lineEdit->text().length() < 6) { ui->infoLabel->setText("输入密码不足6位!"); ui->lineEdit->clear(); } else { ui->infoLabel->setText("密码错误,请重新输入"); ui->lineEdit->clear(); }}
锁屏界面由一个QLineEdit和一个QLabel组成,支持密码输入和错误提示。
转载地址:http://lmsyz.baihongyu.com/