博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Qt - 锁屏界面加虚拟小键盘
阅读量:4876 次
发布时间:2019-06-11

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

一、实现效果

img

鼠标点击“密码输入栏”,弹出虚拟键盘,输入锁屏密码后,点击虚拟键盘外部区域,则会隐藏虚拟键盘,再点击登录,成功进入主界面。

二、虚拟键盘-程序设计

2.1 frmNum.h

#ifndef FRMNUM_H#define FRMNUM_H#include 
#include
#include
#include
namespace Ui{ class frmNum;}class frmNum : public QWidget{ Q_OBJECTpublic: explicit frmNum(QWidget *parent =nullptr); ~frmNum(); //单例模式,保证一个程序只存在一个输入法实例对象 static frmNum *Instance() { if (!_instance) { _instance = new frmNum; } return _instance; } void Init(QString style, int fontSize); //初始化窗口,包括字体大小protected: //事件过滤器:处理鼠标按下弹出小键盘 bool eventFilter(QObject *obj, QEvent *event);private slots: //焦点改变事件槽函数处理 void focusChanged(QWidget *oldWidget, QWidget *nowWidget); //小键盘按键处理槽函数 void btn_clicked(); //改变小键盘样式 void changeStyle(QString topColor, QString bottomColor, QString borderColor, QString textColor); //定时器处理退格键 void reClicked();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(); //clear当前焦点控件的一个字符};#endif // FRMNUM_H

上面是“虚拟键盘程序”的头文件,这里使用了单例模式,保证一个程序只存在一个输入法实例对象。

2.2 frmNum.cpp

#include "frmnum.h"#include "ui_frmnum.h"#include 
#include
frmNum *frmNum::_instance = nullptr;frmNum::frmNum(QWidget *parent) : QWidget(parent), ui(new Ui::frmNum){ ui->setupUi(this); //初始化窗口 Init("black",20); //黑色,字体大小为20px ui->btnClear->setFocus(); ui->btnClear->setShortcut(QKeySequence::InsertParagraphSeparator); ui->btnClear->setShortcut(Qt::Key_Enter); ui->btnClear->setShortcut(Qt::Key_Return);}frmNum::~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; //如果需要更改输入法面板的样式,改变style这个形式参数即可 //blue--淡蓝色 dev--dev风格 black--黑色 brown--灰黑色 lightgray--浅灰色 darkgray--深灰色 gray--灰色 silvery--银色 this->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
btn = this->findChildren
(); foreach (QPushButton * b, btn) { connect(b, 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){ //qDebug() << "oldWidget:" << oldWidget << " nowWidget:" << nowWidget; if (nowWidget != nullptr && !this->isAncestorOf(nowWidget)) { /*在Qt5和linux系统中(嵌入式linux除外),当输入法面板关闭时,焦点会变成无,然后焦点会再次移到焦点控件处 这样导致输入法面板的关闭按钮不起作用,关闭后马上有控件获取焦点又显示. 为此,增加判断,当焦点是从有对象转为无对象再转为有对象时不要显示. 这里又要多一个判断,万一首个窗体的第一个焦点就是落在可输入的对象中,则要过滤掉*/ #ifndef __arm__ if (oldWidget == nullptr && !isFirst) { return; } #endif isFirst = false; if (nowWidget->inherits("QLineEdit")) { currentLineEdit = static_cast
(nowWidget); currentEditType = "QLineEdit"; this->setVisible(true); } else { currentWidget = nullptr; currentLineEdit = nullptr; currentEditType = ""; this->setVisible(false); } QRect rect = nowWidget->rect(); QPoint pos = QPoint(rect.left(), rect.bottom() + 2); pos = nowWidget->mapToGlobal(pos); 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 = static_cast
(obj); if (checkPress()) { isPressBackBtn = true; backBtnTimert->start(500); } } return false; } else if (event->type() == QEvent::MouseButtonRelease) { btnPress = static_cast
(obj); if (checkPress()) { isPressBackBtn = false; backBtnTimert->stop(); } return false; } return QWidget::eventFilter(obj, event);}//校验当前长按的按钮bool frmNum::checkPress(){ //只有属于数字键盘的合法按钮才继续处理 bool num_ok = btnPress->property("btnNum").toBool(); bool other_ok = btnPress->property("btnOther").toBool(); if (num_ok || other_ok) { return true; } return false;}//定时器处理退格键void frmNum::reClicked(){ if (isPressBackBtn) { backBtnTimert->setInterval(30); btnPress->click(); }}//小键盘按键处理槽函数void frmNum::btn_clicked(){ //如果当前焦点控件类型为空,则返回不需要继续处理 if (currentEditType == "") { return; } QPushButton *btn = static_cast
(sender()); QString objectName = btn->objectName(); if (objectName == "btnDelete") { this->deleteValue(); } else if (objectName == "btnClear") { this->clearValue(); } else { QString value = btn->text(); this->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 == "dev") { changeStyle("#C0D3EB", "#BCCFE7", "#B4C2D7", "#324C6C"); } else if (currentStyle == "gray") { changeStyle("#E4E4E4", "#A2A2A2", "#A9A9A9", "#000000"); } else if (currentStyle == "lightgray") { changeStyle("#EEEEEE", "#E5E5E5", "#D4D0C8", "#6F6F6F"); } else if (currentStyle == "darkgray") { changeStyle("#D8D9DE", "#C8C8D0", "#A9ACB5", "#5D5C6C"); } else if (currentStyle == "black") { changeStyle("#4D4D4D", "#292929", "#D9D9D9", "#CACAD0"); } else if (currentStyle == "brown") { changeStyle("#667481", "#566373", "#C2CCD8", "#E7ECF0"); } else if (currentStyle == "silvery") { changeStyle("#E1E4E6", "#CCD3D9", "#B2B6B9", "#000000"); }}//改变小键盘样式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(""));}

上面是“虚拟键盘程序”的源代码,当检测焦点在 QlineEdit 单行输入栏上,则显示虚拟键盘,否则隐藏虚拟键盘。虚拟键盘调出的显示位置跟 QlineEdit 对齐,尝试过但还是无法改变显示位置。另外可以对上面代码进行扩展,扩展支持 QTextEdit、QTextBrowser 等窗口部件。

2.3 frmNum.ui

img

三、锁屏界面-程序设计

3.1 lockWin.h

/*注:注意.ui文件中的dailog的focusPolicy要设置为clickFocus*/#ifndef LOCKWIN_H#define LOCKWIN_H#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 slots: void on_cancelButton_clicked(); //取消按钮-点击槽函数:清空密码栏 void on_loginButton_clicked(); //登录按钮-点击槽函数private: Ui::LoginWin *ui; bool eventFilter(QObject *watched, QEvent *event); //事件过滤器 frmNum *myFrmnum;};#endif // LOCKWIN_H

上面是“锁屏界面程序”的头文件,这里定义了一个“虚拟键盘”类对象指针,锁屏密码设置为“123456”。

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);    //通过正则表达式设置"密码输入栏",只能输入数字0-9,不超过6位    QValidator *accountValidator = new QRegExpValidator(QRegExp("[0-9]{6}"));    ui->lineEdit->setValidator(accountValidator);    myFrmnum = new frmNum(this);}LockWin::~LockWin(){    delete ui;}//事件过滤器bool  LockWin::eventFilter(QObject *watched, QEvent *event){    if(watched ==ui->lineEdit)    {        if(QEvent::FocusIn == event->type())        {            if(ui->lineEdit->echoMode()==QLineEdit::Normal)            {                ui->lineEdit->clear();            }            ui->lineEdit->setEchoMode(QLineEdit::Password);        }    }    // 最后将事件交给上层对话框    return QWidget::eventFilter(watched,event);}//---------------------------slots-----------------------------------------------//取消按钮-点击槽函数:清空密码栏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();    }}

上面是“锁屏界面程序”的源文件,这里使用了this->setWindowModality(Qt::WindowModal)来成为模态对话框阻塞主界面,即锁屏界面关闭才能进入主界面。

3.3 lockWin.ui

img

注:主窗口程序部分这里不再贴出,就是新建工程时系统生成的widget.h、widget.cpp、widget.ui。

转载于:https://www.cnblogs.com/linuxAndMcu/p/10912656.html

你可能感兴趣的文章
[LeetCode] 合并K个排序链表
查看>>
leetcode--Balanced Binary Tree
查看>>
shell字符串处理
查看>>
js 数据绑定
查看>>
jsp的C标签一般使用方法以及js接收servlet中的对象及对象数字
查看>>
H5 简介
查看>>
window.frameElement的使用
查看>>
nl命令
查看>>
如何使用jQuery $.post() 方法实现前后台数据传递
查看>>
Using Flash Builder with Flash Professional
查看>>
jsp/post中文乱码问题
查看>>
C# 插入或删除word分页符
查看>>
数据库数据的查询----连接查询
查看>>
Git使用教程【转】
查看>>
html图片设置fixed消失,为什么fixed后,DIV7消失了,怎么显示出来?
查看>>
html5隐藏自定义控制按钮,用仿ActionScript的语法来编写html5——第七篇,自定义按钮...
查看>>
找不到可安装的ISAM ,asp.net读取数据丢失,解决的一列里有字符与数字的
查看>>
Java学习笔记三(对象的基本思想一)
查看>>
Bezier贝塞尔曲线的原理、二次贝塞尔曲线的实现
查看>>
Java程序(文件操作)
查看>>