Qt 软键盘的实现(QWidget),支持中文输入法、数字、英文切换

**出发点:由于Qt自带的软键盘是QML的,如果使用QWidget模式去编写调用自带的软键盘的话,在ARM下运行会全屏漆黑,并不是我们想要的效果,所以,在网上搜了很多的资料,自己去做了自制键盘,在项目中使用。 **

新建一个keyboard的Demo

以下是键盘的布局
在这里插入图片描述

键盘初始化

准备好26个输入的字符列表,用作大小写、数字切换

   QMap<int,QList<QString>> modelMap;
   QList<QString> firstList,secordList,thirdList;
   firstList<<"Q"<<"W"<<"E"<<"R"<<"T"<<"Y"<<"U"<<"I"<<"O"<<"P"<<"A"<<"S"<<"D"<<"F"<<"G"<<"H"<<"J"<<"K"<<"L"<<"Z"<<"X"<<"C"<<"V"<<"B"<<"N"<<"M";
   secordList<<"q"<<"w"<<"e"<<"r"<<"t"<<"y"<<"u"<<"i"<<"o"<<"p"<<"a"<<"s"<<"d"<<"f"<<"g"<<"h"<<"j"<<"k"<<"l"<<"z"<<"x"<<"c"<<"v"<<"b"<<"n"<<"m";
   thirdList<<"1"<<"2"<<"3"<<"4"<<"5"<<"6"<<"7"<<"8"<<"9"<<"0"<<"~"<<"!"<<"@"<<"#"<<"%"<<"^"<<"&"<<"*"<<"?"<<"("<<")"<<"-"<<"_"<<":"<<";"<<"/";
   modelMap.insert(1,firstList);
   modelMap.insert(2,secordList);
   modelMap.insert(3,thirdList);

以下是大小写、数字切换的函数接口

/*************************************************
Function:modeExchange// 函数名称
Description: 模式切换// 函数功能、性能等的描述
Input: int modeNum  -> 模式值// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::modeExchange(int modeNum)
{
    switch (modeNum) {
        case 2://小写
            for (int i=0;i<modelMap.value(2).length();i++){
                btngroup->button(i+1)->setText(modelMap.value(2).at(i));
            }
            break;
        case 1://大写
            for (int i=0;i<modelMap.value(2).length();i++){
                btngroup->button(i+1)->setText(modelMap.value(1).at(i));
            }
            break;
        case 3://数字
            for (int i=0;i<modelMap.value(2).length();i++){
                btngroup->button(i+1)->setText(modelMap.value(3).at(i));
            }
            break;
        default:
            break;

    }
}

26个字符按键输入函数接口

/*************************************************
Function:onClick// 函数名称
Description: 模式切换// 函数功能、性能等的描述
Input: int modeNum  -> 模式值// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::onClick(int value)
{
    QString buffer;
    switch (modeIndex) {
        case 0:
            buffer=modelMap.value(2).at(value-1);
            break;
        case 1:
            buffer=modelMap.value(1).at(value-1);
            break;
        case 2:
            buffer=modelMap.value(3).at(value-1);
            break;
      default:
            break;
    } 
    if(isChinese){
        recordBuf+=buffer;
       findFontData(recordBuf);
    }else{
        recordBuf.clear();
        insertValue(buffer);
    }
}

除了26个基本字符按键外,还有一些功能按键,如数字切换键,大小写切换键,中英文切换键,删除键等等。。。。。

/*************************************************
Function:otherBtnClick()// 函数名称
Description: 功能按键槽函数// 函数功能、性能等的描述
Input: 无// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::otherBtnClick()
{
     QPushButton *b = (QPushButton *)sender();
     if(b==ui->spacebtn){//空格
         recordBuf+=" ";
         findFontData(recordBuf);
     }else if(b==ui->keydelbtn){//删除
         if(recordBuf.length()!=0){
            recordBuf.remove(recordBuf.length()-1,1);
            findFontData(recordBuf);
         }else{
                deleteValue();
         }
     }else if((b==ui->oneSwitchbtn||b==ui->oneSwitchbtn)&&numFlag==false){//大小写
        if(sizeFlag==true){//小写
            modeIndex=1;
            sizeFlag=false;
            modeExchange(1);
        }
        else{
             modeIndex=0;
             sizeFlag=true;
             modeExchange(2);
        }
     }else if(b==ui->numbtn){
         if(!numFlag){
            modeIndex=2;
            modeExchange(3);
         }
         else{
             modeIndex=0;
             modeExchange(2);
         }
         numFlag=!numFlag;
     } else if(b==ui->ChEnbtn&&numFlag==false){
            if(isChinese){
               ui->ChEnbtn->setText("英文");
            }else{
               ui->ChEnbtn->setText("中文");
            }
            isChinese = !isChinese;
     }else if(b==ui->keyexitbtn) {
         this->close();
     }
}

按键功能接口编写好后,接下来我们需要加载自定义的字库
在这里插入图片描述

/*************************************************
Function:loadFontData// 函数名称
Description: 加载字库函数// 函数功能、性能等的描述
Input: 无// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::loadFontData()
{

        QFile pinyin(":/pinyin.txt");
        if (! pinyin.open(QIODevice::ReadOnly)) {
            qDebug() << "Open pinyin file failed!";
           return;
        }
        while (! pinyin.atEnd()) {
              QString buf = QString::fromUtf8(pinyin.readLine()).trimmed();
             // qDebug()<<buf;
              if (buf.isEmpty())
                  continue;
              /* 去除#号后的注释内容 */
              if (buf.left(1) == "#")
                  continue;
              buf=buf.replace("\t"," ");
             // qDebug()<<buf;
              /* 正则匹配词组内容并通过组捕获获取'词组'和'拼音' */
              QRegExp regExp("(\\S+) : ([\\S ]+)");
              int pos = 0;
              while ((pos = regExp.indexIn(buf, pos)) != -1) {
                  pos += regExp.matchedLength();
                  QString second = regExp.cap(1);  /* 词组 */
                  QString first = regExp.cap(2); /* 拼音 */
                  QStringList strList = first.split(" ");
                  QString abb;
                  for (int i = 0; i < strList.count(); i++) {
                      /* 获得拼音词组的首字母(用于缩写匹配) */
                      abb += strList.at(i).left(1);
                  }
                  QList<QPair<QString, QString> > &tmp = m_data[first.left(1)];
                  /* 将'拼音(缩写)'和'词组'写入匹配容器 */
                  tmp.append(qMakePair(abb, second));
                  /* 将'拼音(全拼)'和'词组'写入匹配容器 */
                  tmp.append(qMakePair(first.remove(" "), second));
              }
          }
         // qDebug()<<m_data["b"];
}

通过用户输入的字符从字库中提取出来

/*************************************************
Function:findFontData()// 函数名称
Description: 从字库中找相对应的中文// 函数功能、性能等的描述
Input: QString text ->输入的字符// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::findFontData(QString text)
{
    for (int i = 0; i < ui->listWidget->count(); i++) {
        QListWidgetItem *item = ui->listWidget->takeItem(i);
        delete item;
        item = NULL;
    }
    ui->listWidget->clear();
    addOneItem(text);
    /* 通过获取首字母索引词库内容,用于加快匹配词(组)。 */
    const QList<QPair<QString, QString> > &tmp = m_data[text.left(1)];
    for (int i = 0; i < tmp.count(); i++) {
        const QPair<QString, QString> &each = tmp.at(i);
        /* 模糊匹配 */
        if (each.first.left(text.count()) != text)
            continue;
        /* 添加到候选栏 */
        addOneItem(each.second);
    }
}
/*************************************************
Function:addOneItem()// 函数名称
Description: 将词组添加到显示列表// 函数功能、性能等的描述
Input: QString text ->从字库中提取出来的词组// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::addOneItem(QString text)
{
    QListWidgetItem *item = new QListWidgetItem(text);
    QFont font;
    font.setPointSize(18);
    font.setBold(true);
    font.setWeight(50);
    item->setFont(font);

    /* 设置文字居中 */
    item->setTextAlignment(Qt::AlignCenter);
    bool isChineseFlag = QRegExp("^[\u4E00-\u9FA5]+").indexIn(text.left(1)) != -1;

    int width = font.pointSize();
    if (isChineseFlag)
        width += text.count()*font.pointSize()*1.5;
    else
        width += text.count()*font.pointSize()*2/3;

    item->setSizeHint(QSize(width, 50));
    ui->listWidget->addItem(item);
}

双击listWidget列表的选项

   connect(ui->listWidget,SIGNAL(itemDoubleClicked(QListWidgetItem *)),this,SLOT(listWidgetDoubleClick(QListWidgetItem *)));

void Dialog::listWidgetDoubleClick(QListWidgetItem *item)
{
    qDebug()<<item->text();
    recordBuf.clear();
    findFontData(recordBuf);
}

删除QlineEdit中的字符

void Dialog::deleteValue()
{
    if (currentEditType == "QLineEdit"){
        currentLineEdit->backspace();
    }
}

插入字符到QLineedit上

/*************************************************
Function:insertValue// 函数名称
Description: 插入值到当前焦点控件// 函数功能、性能等的描述
Input: QString value ->插入的字符// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::insertValue(QString value)
{
    if (currentEditType == "QLineEdit"){
        currentLineEdit->insert(value);
    }
}

接口写好后,接下来是触发启动键盘的条件

首先安装事件过滤器
qApp->installEventFilter(this);
绑定全局焦点信号槽
connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)),
            this, SLOT(focusChanged(QWidget *, QWidget *)));
/*************************************************
Function:focusChanged// 函数名称
Description: 判断焦点改变// 函数功能、性能等的描述
Input: QWidget *oldWidget ->上一个控件
       QWidget *nowWidget ->新控件// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
void Dialog::focusChanged(QWidget *oldWidget, QWidget *nowWidget)
{
    qDebug() << "oldWidget:" << oldWidget << " nowWidget:" << nowWidget;
    if (nowWidget != nullptr && !this->isAncestorOf(nowWidget)){
                if (oldWidget == nullptr && !isFirst){
                    return;
                }
        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);
        }
    }
}
/*************************************************
Function:eventFilter// 函数名称
Description://事件过滤器 QLineEdit弹出小键盘 // 函数功能、性能等的描述
Input: QObject *obj   ->对象
       QEvent *event  ->事件// 输入参数说明,包括每个参数的作用、取值说明及参数间关系。
Return: 无// 函数返回值的说明
*************************************************/
bool Dialog::eventFilter(QObject *obj, QEvent *event)
{
    //qDebug()<<__func__<<":"<<obj->objectName();
    if (event->type() == QEvent::MouseButtonPress){
        //确保每次点击输入栏都弹出虚拟键盘
        if (currentEditType == "QLineEdit"){

            this->setVisible(true);
        }
        return false;
    }
    return QWidget::eventFilter(obj, event);
}

部分效果图如下

由于拍的视频太大,Gif图上传不了,只能截取部分图出来
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论
软键盘是一种虚拟的输入设备,它可以在屏幕上显示出来,用户可以通过触摸屏幕上的按键来输入文字。在Qt开发中,软键盘可以被作为一个部件来实现,以支持英文输入。 首先,我们需要定义软键盘的布局。这可以通过Qt提供的各种部件(如QLabel、QPushButton等)和布局管理器(如QGridLayout、QVBoxLayout、QHBoxLayout等)来实现。通过将这些部件放置在一个QWidget中,并将其设置为QWidget的子部件,我们就可以得到一个可自由调整大小并在屏幕上显示的软键盘。 其次,我们需要定义软键盘的输入行为。这可以通过为软键盘的按钮定义信号槽(或回调函数)来完成。在每次按钮被按下时,软键盘应该将相应的字符输入到客户端应用程序中。对于中英文输入,我们可以使用QInputMethod类来完成输入法的切换,并根据当前输入法状态将相应的字符输入到客户端应用程序中。 最后,我们需要将软键盘部件与客户端应用程序连接起来。在Qt中,部件之间的交互可以通过信号槽机制来完成。我们可以定义一个信号,为软键盘中的按钮连接该信号,当按钮被按下时,该信号会被发射。客户端应用程序中会定义一个槽函数来接收该信号,并将相应的字符输入到编辑框中。 综上所述,通过以上三个步骤,我们可以在Qt实现一个支持英文输入的软键盘部件。这个软键盘部件可以被集成到客户端应用程序中,并提供用户在不同场景下的方便输入体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赟赟、嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值