博客
关于我
Qt - 锁屏界面加虚拟小键盘
阅读量:452 次
发布时间:2019-03-06

本文共 8427 字,大约阅读时间需要 28 分钟。

虚拟键盘与锁屏界面系统设计


一、实现效果

系统通过虚拟键盘实现密码输入功能。当用户点击“密码输入栏”,弹出虚拟键盘,输入锁屏密码后,点击虚拟键盘外部区域,虚拟键盘将隐藏。再次点击登录按钮,用户即可成功进入主界面。


二、虚拟键盘程序设计

虚拟键盘采用C++和Qt框架开发,支持单例模式,确保程序中只存在一个输入法实例对象。以下是相关实现细节:

2.1 frmNum.h
#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
2.2 frmNum.cpp
#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(""));}
2.3 frmNum.ui

虚拟键盘界面由多个按钮组成,支持数字输入和特殊功能键,美观且易于使用。


三、锁屏界面程序设计

锁屏界面采用QDialog实现,以下是相关实现细节:

3.1 lockWin.h
#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
3.2 lockWin.cpp
#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();    }}
3.3 lockWin.ui

锁屏界面由一个QLineEdit和一个QLabel组成,支持密码输入和错误提示。

转载地址:http://lmsyz.baihongyu.com/

你可能感兴趣的文章
MyEcplise中SpringBoot怎样定制启动banner?
查看>>
MyPython
查看>>
MTD技术介绍
查看>>
MySQL
查看>>
MySQL
查看>>
mysql
查看>>
MTK Android 如何获取系统权限
查看>>
MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况、SQL 优化
查看>>
MySQL - ERROR 1406
查看>>
mysql - 视图
查看>>
MySQL - 解读MySQL事务与锁机制
查看>>
MTTR、MTBF、MTTF的大白话理解
查看>>
mt_rand
查看>>
mysql -存储过程
查看>>
mysql /*! 50100 ... */ 条件编译
查看>>
mudbox卸载/完美解决安装失败/如何彻底卸载清除干净mudbox各种残留注册表和文件的方法...
查看>>
mysql 1264_关于mysql 出现 1264 Out of range value for column 错误的解决办法
查看>>
mysql 1593_Linux高可用(HA)之MySQL主从复制中出现1593错误码的低级错误
查看>>
mysql 5.6 修改端口_mysql5.6.24怎么修改端口号
查看>>
MySQL 8.0 恢复孤立文件每表ibd文件
查看>>