龙空技术网

Qt - 锁屏界面加虚拟小键盘

QT教程 474

前言:

现在咱们对“焦点控件怎么设置快捷键”大约比较珍视,兄弟们都想要剖析一些“焦点控件怎么设置快捷键”的相关资讯。那么小编同时在网络上搜集了一些有关“焦点控件怎么设置快捷键””的相关文章,希望咱们能喜欢,各位老铁们快快来学习一下吧!

一、实现效果

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

二、虚拟键盘-程序设计2.1 frmNum.h

#ifndef FRMNUM_H#define FRMNUM_H#include <QWidget>#include <QLineEdit>#include <QPushButton>#include <QTimer>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 <QShortcut>#include <QDebug>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<QPushButton *> btn = this->findChildren<QPushButton *>();    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<QLineEdit *>(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<QPushButton *>(obj);            if (checkPress())            {                isPressBackBtn = true;                backBtnTimert->start(500);            }        }        return false;    }    else if (event->type() == QEvent::MouseButtonRelease)    {        btnPress = static_cast<QPushButton *>(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<QPushButton *>(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

三、锁屏界面-程序设计3.1 lockWin.h

/*注:注意.ui文件中的dailog的focusPolicy要设置为clickFocus*/#ifndef LOCKWIN_H#define LOCKWIN_H#include <QDialog>#include <QDebug>#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)来成为模态对话框阻塞主界面,即锁屏界面关闭才能进入主界面。

点击领取Qt学习资料+视频教程~「链接」

标签: #焦点控件怎么设置快捷键