续上篇介绍了嵌入式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;
}
如有其他需求,可私信