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

续上篇介绍了嵌入式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(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(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;
}

如有其他需求,可私信

你可能感兴趣的:(C++,Qt,-,Linux,嵌入式,开发,Linux,输入法,中文,c++)