中文输入法开发-关键代码

续上篇介绍了嵌入式Linux下中文输入法,

嵌入式Linux下开发中文输入法_嵌入式输入法_小刚学長的博客-CSDN博客

本篇继续介绍核心关键功能

展现效果图如下:

 

 

1、如何跟应用关联起来,比如说,希望当LineEdit 输入状态激活后,自动调出输入法?

这里关键要处理

  • 在app处理键盘按键消息前处理事件

首先要输入法的Dialog里面重载evenFilter函数,用于事件过滤

protected:
    bool eventFilter(QObject *obj, QEvent *event) override;

想办法在初始化输入法时候

bool ImeInput::Init(const char *sysDict,const char *userDict,const QString &qss)
{

// ......

    qApp->installEventFilter(this); 


}

这样app里的输入事件,将先在输入法里处理

在app侧,需要在main函数里调用。注意必须在MainWindow之前

int main(int argc, char *argv[])
{

    QApplication a(argc, argv);

    // 我这里将输入封装成so,调用时候采用 单例模式 - Init 接口,这样方便使用,代码封装也好一点
    ImePtr->Init(pathDict.c_str(),pathUser.c_str(),QString("white"));

    MainWindow w;
    w.show();    
    return a.exec();

}

2、eventFilter 如何进行过滤消息?

还是直接上code方便点,此处代码是输入内部的

bool ImeInput::eventFilter(QObject *obj, QEvent *event)
{
    // S1 检测obj是否需要自己监视的,比如类型 QLineEdit
    //  if(obj->inherits("QLineEdit")) 等,先过滤,不需要监控的obj直接返回
    if(InputObj::IsVaild(obj) == 0)
    {
        return QObject::eventFilter(obj, event);
    }

    mMutex.lock();
    // S2  这里做了小心思,就是有些虽然类型==QLineEdit,但不需要中文输入,把这些obj的指针放在mGrepObj里面,自然如果当前obj是这个map里面的,就不需要中文输入
    if(mGrepObj->contains(obj))
    {
        mMutex.unlock();
        return QObject::eventFilter(obj, event);
    }
    mMutex.unlock();

    // S3 按键按下
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        // 自然要处理,逻辑就复杂了:总的来说此时要处理:普通a~z,数字0~9,标点符号,特殊控制符还有一些组合键
        if(DeliverPressEvent(keyEvent))
        {
            return true;
        }
        else
        {
            return QObject::eventFilter(obj, event);
        }
    }
    else if (event->type() == QEvent::KeyRelease)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if(DeliverReleaseEvent(keyEvent))
        {
            return true;
        }
        else
        {
            return QObject::eventFilter(obj, event);
        }
    }
    else if(event->type() == QEvent::FocusIn)
    {        

        //S4 该obj一次获取焦点,因此需要输入法Dailog移动到该obj下
        QWidget *call = (QWidget *)obj;
        QPoint ps = call->mapToGlobal(call->rect().topLeft());

        mObjRect = QRect(ps.x(),ps.y(),call->rect().width(),call->rect().height());
       

        UpdateLanguageState(true);

        /*add new*/
        mInputObj->SetObj(obj);
        return QObject::eventFilter(obj, event);
    }
    else if(event->type() == QEvent::FocusOut)
    {
 // 失去焦点,这个简单,但也必不可少,主要是要关闭
        if(mInputObj->IsVaild())
        {
            UpdateLanguageState(true);
        }

        mInputObj->Clear();
        this->hide();

        qDebug("[%s] QEvent::FocusOut ",obj->objectName().toStdString().c_str());
        return QObject::eventFilter(obj, event);
    }
    else
    {
        return QObject::eventFilter(obj, event);
    }
}

3、字典里查询出来的是什么格式?

字典的接口,要输入查询的字符串(这个是输入的,当然要进行一些筛选,例如超长字符、例如i、v字符开头等等这些要在查询之前处理掉),然后返回结果(数组),为了分页显示方便点,需要把结果放在一个list里面

int ImeInput::ImSearch(QStringList &list)
{
    static const int MAX_OUT = 256;
    ime_pinyin::char16 buf[MAX_OUT] = {0};
    list.clear();

    if(mInputStr.isEmpty())
    {
        return 0;
    }
    else
    {
        /*获取可查询的*/  // mInputStr就是输入字符,当然这里已经优化后的
        QString str = GetSearchStr(mInputStr);

        // 如果str是错误的,这里会崩溃的,因此,必须要先过滤优化
        size_t qty = ime_pinyin::im_search(str.toUtf8().data(), str.size());

        // 数组分页操作,mSelectPage是当前也
        size_t start = mSelectPage * IME_SHOW_NUMS;
        size_t i = start;

        for (i = start; i < qMin(qty,(start+IME_SHOW_NUMS)); i++)
        {
            ime_pinyin::im_get_candidate(i, buf, MAX_OUT - 1);
            list.append(QString::fromUtf16(buf));
        }

        return qty;
    }
}

4、如何显示到控件?

显示到控件,那也比较简单,当判断到当前选择了list的哪个,就可以

bool InputObj::SetText(const QString &str)
{
    bool ret = false;
// mInObj就是当前应用层obj指针,根据focus in 就可以获得
    if(mInObj)
    {
// 需要注意的,这里需要insert,而不是settext,不同控件insert方法不一样。主要考虑到光标位置
        switch (mObjType)
        {
        case OBJ_LINEEDIT:
            ((QLineEdit *)mInObj)->insert(str);
            ret = true;
            break;
        case OBJ_TEXTEDIT:
            ((QTextEdit *)mInObj)->insertPlainText(str);
            ret = true;
            break;
        case OBJ_TEXTBROWSER:
            ((QTextBrowser *)mInObj)->insertPlainText(str);
            ret = true;
            break;
        case OBJ_PLAIN_TEXTEDIT:
            ((QPlainTextEdit *)mInObj)->insertPlainText(str);
            ret = true;
            break;
        default:
            break;
        }
    }

    return ret;
}

如有其他需求,可私信

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/45247.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一文看懂FIFO!

什么是FIFO&#xff1f; FIFO: First in, First out 代表先进的数据先出 &#xff0c;后进的数据后出。 为什么需要FIFO&#xff1f; FIFO存储器是系统的缓冲环节&#xff0c;如果没有FIFO存储器&#xff0c;整个系统就不可能正常工作。 FIFO的功能可以概括为 &#xff0…

Python Flask构建微信小程序订餐系统 (十二)

🔥 创建切换商品分类状态的JS文件 🔥 ; var food_act_ops={init:function(){this.eventBind();},eventBind:function(){//表示作用域var that = this;$(".wrap_search select[name=status]").change(function(){$(".wrap_search").submit();});$(&qu…

java根据模板导出word

java根据模板导出word 日常开发中&#xff0c;常常会遇到各种各样的表格进行导出&#xff0c;比较好的办法就是提前弄好word模版&#xff0c;再通过遍历的方式进行导出文档 1、制作word模版 模版编写 内容替换 目标下面模版进行多页展示 将word转换成xml 将xml格式化 再将x…

HCIP——OSPF基础

OSPF基础 一、OSPF基础二、OSPF的区域划分三、OSPF的数据包hello包数据库描述包DBD包链路状态请求包LSR包链路状态更新包LSU包链路状态确认包LSAck包 四、OSPF的状态机五、OSPF的工作过程六、链路状态型的路由生成过程七、条件匹配五、OSPF数据包头部八、OSPF的接口网络类型 一…

STC12C5A系列单片机内部 EEPROM 的应用

参考范例程序。 eeprom.c #include "eeprom.h"/*---------------------------- Disable ISP/IAP/EEPROM function Make MCU in a safe state ----------------------------*/ void IapIdle() {IAP_CONTR 0; //Close IAP functionIAP_CMD 0; …

ubuntu docker离线安装docker(.deb包方式)(成功)(附卸载方法)

参考文章&#xff1a;Install Docker Engine on Ubuntu 文章目录 安装步骤下载安装包拷贝到目标主机并执行安装命令 验证拉取运行容器测试build dockerfile测试持久运行容器测试主机重启后&#xff0c;docker各服务是否正常自启 卸载方法附&#xff1a;各安装包作用说明&#x…

静态路由小实验

文章目录 一、实验要求及拓扑图二、实验步骤三、思考题 一、实验要求及拓扑图 二、实验步骤 1、创建VLAN&#xff0c;将端口划入vlan 在交换机S3、S4上创建VLAN10、20 Switch(config)#vl 10 Switch(config-vlan)#vl 20 S3(config)#int f0/3 S3(config-if)#switchport access …

音视频——帧内预测

H264编码(帧内预测) 在帧内预测模式中&#xff0c;预测块P是基于已编码重建块和当前块形成的。对亮度像素而言&#xff0c;P块用于44子块或者1616宏块的相关操作。44亮度子块有9种可选预测模式&#xff0c;独立预测每一个44亮度子块&#xff0c;适用于带有大量细节的图像编码&…

uniapp 之 微信小程序、支付宝小程序 对于自定义导航栏的不同

目录 前言 微信小程序 代码 支付宝小程序 首页配置文件 二级菜单页面 配置 总结 不同 相同 前言 小程序都是 uni-app 写的 不是原生 微信小程序 代码 pages.json文件中配置 重点&#xff1a; "navigationStyle": "custom", // 导航栏样式…

MAC 推送证书不受信任

配置推送证书的时候&#xff0c;一打开就变成不受信任&#xff0c;搜了很多解决版本。 由于苹果修改相关规定&#xff0c;推送证书 打开Apple PKI - Apple 下载AppleWWDRCA文件&#xff0c;选择G4,双击安装之后&#xff0c;证书已经变为受信任。 AppleWWDRCA(Apple Worldwid…

代码随想录day12 | [前、中、后、层]二叉树的遍历迭代法和递归法

文章目录 一、前后中序递归法二、前后序迭代法三、中序遍历迭代法四、层序遍历 递归三部曲&#xff1a; 1️⃣ 第一步确定递归函数的返回值和参数 2️⃣第二步确定递归的终止条件 3️⃣第三步确定单层递归处理的逻辑 一、前后中序递归法 前序遍历二叉树 class Solution { pr…

关于应用在Google Play的元数据优化

应用标题中的关键词权重最大&#xff0c;其次是简短描述中的关键词&#xff0c;最后是长描述关键词&#xff0c;了解这些就能够很好的提高应用的可见度&#xff0c;下载量和整体成功率。 1&#xff0c;标题。 Google Play最多允许标题容纳30个字符&#xff0c;关键词的频率和密…

ARP协议(地址解析协议)

文章目录 ARP协议&#xff08;地址解析协议&#xff09;MAC地址ARP协议ARP具体实现同一链路不同链路 ARP 缓存缓存查询 APR请求/响应报文 ARP协议&#xff08;地址解析协议&#xff09; MAC地址 MAC 地址的全称是 Media Access Control Address&#xff0c;即媒体访问控制地址…

flask框架的请求处理逻辑

Django 和 Flask 是 Python 的两个非常流行的 Web 框架&#xff0c;它们对 HTTP 请求的处理方式有一些区别。 在 Django 中&#xff0c;当你的应用接收到一个 HTTP 请求时&#xff0c;Django 会将请求封装为一个 HttpRequest 对象&#xff0c;然后通过视图函数的参数传递这个对…

Kubernetes_核心组件_kubelet_kubelet服务全解析(二)

文章目录 前言kubelet 架构kubelet 职责Node管理(节点管理)Pod管理 kubelet管理Podkubelet如何管理当前节点上所有Podkubelet三个端口kubelet获取Pod清单kubelet通过CRI接口管理Pod以及里面的容器 PodWorker的工作细节PodWorker的工作细节PLEG组件PLEG报错 kubelet创建并启动Po…

kafka权威指南学习以及kafka生产配置

0、kafka常用命令 Kafka是一个分布式流处理平台&#xff0c;它具有高度可扩展性和容错性。以下是Kafka最新版本中常用的一些命令&#xff1a; 创建一个主题&#xff08;topic&#xff09;&#xff1a; bin/kafka-topics.sh --create --topic my-topic --partitions 3 --replic…

【高危】Foxit 福昕PDF阅读器 Field Calculate 释放后使用漏洞(PoC)

漏洞描述 Foxit PDF阅读器是福昕软件公司推出的一款广泛使用的PDF文档阅读器。 在受影响版本中&#xff0c;由于其javascript引擎存在use-after-free漏洞&#xff0c;攻击者可以构造恶意的PDF文件&#xff0c;通过文件中包含的deletePages()等操作使福昕PDF阅读器过早删除与页…

若依分离版——解决配置双数据源oracle,mysql分页错误问题

1. 按照若依的手册配置双数据源mysql&#xff0c;oracle 2. 在service指定 数据源 DataSource(value DataSourceType.MASTER) 或者DataSource(value DataSourceType.SLAVE) Service public class SysPostServiceImpl implements ISysPostService {/*** 查询岗位信息集合* …

9.python设计模式【外观模式】

内容&#xff1a;为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个高层接口&#xff0c;这个接口使得这一个子系统更加容易使用。 角色&#xff1a; 外观&#xff08;facade&#xff09;子类系统&#xff08;subsystem classes&#xff09; UML图 举…

react实现页面动态表单设计器(自定义推拽表单)

react实现页面动态表单设计器&#xff08;自定义推拽表单&#xff09; 实现效果安装插件使用组件介绍基本设置&#xff0c;可设置控件标签&#xff0c;是否必填&#xff0c;校验规则校验规则有如下几种多选&#xff0c;下拉&#xff0c;单选可动态设置每个选择的label以及值 实…
最新文章