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

本文共 8608 字,大约阅读时间需要 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_OBJECT
public:
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_OBJECT
public:
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/

你可能感兴趣的文章
mysql 快照读 幻读_innodb当前读 与 快照读 and rr级别是否真正避免了幻读
查看>>
MySQL 快速创建千万级测试数据
查看>>
mysql 快速自增假数据, 新增假数据,mysql自增假数据
查看>>
MySql 手动执行主从备份
查看>>
Mysql 批量修改四种方式效率对比(一)
查看>>
Mysql 报错 Field 'id' doesn't have a default value
查看>>
MySQL 报错:Duplicate entry 'xxx' for key 'UNIQ_XXXX'
查看>>
Mysql 拼接多个字段作为查询条件查询方法
查看>>
mysql 排序id_mysql如何按特定id排序
查看>>
Mysql 提示:Communication link failure
查看>>
mysql 插入是否成功_PDO mysql:如何知道插入是否成功
查看>>
Mysql 数据库InnoDB存储引擎中主要组件的刷新清理条件:脏页、RedoLog重做日志、Insert Buffer或ChangeBuffer、Undo Log
查看>>
mysql 数据库中 count(*),count(1),count(列名)区别和效率问题
查看>>
mysql 数据库备份及ibdata1的瘦身
查看>>
MySQL 数据库备份种类以及常用备份工具汇总
查看>>
mysql 数据库存储引擎怎么选择?快来看看性能测试吧
查看>>
MySQL 数据库操作指南:学习如何使用 Python 进行增删改查操作
查看>>
MySQL 数据库的高可用性分析
查看>>
MySQL 数据库设计总结
查看>>
Mysql 数据库重置ID排序
查看>>