QT学习笔记-QT5.15编译及安装谷歌拼音输入法(QtInputMethod_GooglePinyin)
- 0、背景
- 1、环境
- 2、下载QtInputMethod_GooglePinyin源码
- 3、使用MinGW64构建套件编译
- 3.1 编译QtInputMethod_GooglePinyin源码
- 3.2、部署tgtsmlInputContextPlugin输入法插件
- 3.3、运行测试程序
- 4、使用MSVC2019_64构建套件编译
- 4.1 编译QtInputMethod_GooglePinyin源码
- 4.2、部署tgtsmlInputContextPlugin输入法插件
- 4.3、运行测试程序,与步骤3.3相同。
- 5、修改QtInputMethod_GooglePinyiny源码解决在分屏情况下虚拟键盘显示越界及不能跨屏显示的问题
0、背景
在使用QT进行嵌入式应用开发时,往往程序最终的运行设备是有触屏的设备。因此,不可避免的会遇到虚拟键盘和中文输入的问题。QT自带一个虚拟键盘,可以在构建套件/plugins/platforminputcontexts目录下看到2个文件:
- qtvirtualkeyboardplugin.dll
- qtvirtualkeyboardplugin.dll.debug
QT自带的虚拟键盘屏幕占比较大,而且很容易挡住输入框,默认不能拖动,不太完美。本就介绍一种替代方式,就是在QT程序中使用GooglePinyin输入法实现虚拟键盘和中文录入。
1、环境
操作系统:windows10专业版
QT版本:5.15.2
QT安装目录:D:\Qt
QT编译套件1:MinGW64
QT编译套件2:MSVC2019_64
2、下载QtInputMethod_GooglePinyin源码
1、下载地址:
https://gitee.com/tgtsml/QtInputMethod_GooglePinyin
2、下载后可以看到压缩包如下图:
3、解压缩后如下图:
4、文件夹的内容如下:
3、使用MinGW64构建套件编译
3.1 编译QtInputMethod_GooglePinyin源码
1、通过qtcreator打开tgtsmlInputContextPlugin.pro工程,本例采用的MinGW64构建套件。如下图:
2、然后分别以debug模式和release模式对tgtsmlInputContextPlugin进行重新构建,会在tgtsmlInputContextPlugin.pro同级目录下生成一个build目录,如下图:
3.2、部署tgtsmlInputContextPlugin输入法插件
1、把上一步编译生成的build/bin/platforminputcontexts目录下的
- tgtsmlInputContextPlugin.dll
- tgtsmlInputContextPlugind.dll
如下图:
复制到D:\Qt\5.15.2\mingw81_64\plugins\platforminputcontexts目录下。
3.3、运行测试程序
1、可以看到下载的源码中包括一个测试程序demo,关键引入输入法虚拟键盘的代码如下:
qputenv("QT_IM_MODULE", QByteArray("tgtsml"));
如下图:
这样当光标聚焦在输入文本框时,会自动弹出虚拟键盘。
运行效果如下:
4、使用MSVC2019_64构建套件编译
4.1 编译QtInputMethod_GooglePinyin源码
1、在项目选项卡中对当前项目的构建套件切换至MSVC2019_64构建套件上,然后对项目进行重新构建,然后这时出现了很多错误,如下图:
2、解决这些问题需要做2个方面的修改。
2.2.1 第1是把所有pro的换行符由Unix(LF)改为Windows(CRLF)
如下,原来是这样:
改成下面这样:
2.2.2 第2是在demo.pro、googlepinyin.pro、plugin.pro 3个文件中增加中文处理的配置,如下:
# 解决msvc构建套件下qtcreator控制台日志中文乱码问题
msvc {
QMAKE_CFLAGS += /utf-8
QMAKE_CXXFLAGS += /utf-8
}
如下图所示:
3、然后再重新构建,就能正常编译过去了。同样使用debug模式和release模式编译完毕后会在会在tgtsmlInputContextPlugin.pro同级目录下生成一个build目录,如果之前在MinGW64构建套件下已生成了,建议先删除,或者在pro文件中指定使用不同构建套件时生成的库放到不同位置,如下:
# 指定输出目录
!msvc {
DESTDIR = ../../wongoing_plugin_bin
}
msvc {
DESTDIR = ../../wongoing_plugin_bin_msvc
}
4.2、部署tgtsmlInputContextPlugin输入法插件
1、把上一步编译生成的build/bin/platforminputcontexts目录下的
- tgtsmlInputContextPlugin.dll
- tgtsmlInputContextPlugind.dll
- tgtsmlInputContextPlugind.pdb
如下图:
复制到D:\Qt\5.15.2\msvc2019_64\plugins\platforminputcontexts目录下。
4.3、运行测试程序,与步骤3.3相同。
5、修改QtInputMethod_GooglePinyiny源码解决在分屏情况下虚拟键盘显示越界及不能跨屏显示的问题
1、当我的笔记本电脑有外接了一个显示时(扩展模式)使用时会出现2个问题,第1个问题是虚拟键盘不能显示到扩展屏幕上,虽然我的demo窗口显示在扩展屏幕。第2个问题,就是当demo窗口(输入框窗口)在主屏幕最右测时,虚拟键盘会有一部分显示不出来,就是显示越界。具体如下图:
上图是虚拟键盘不能跨屏幕显示,只能显示在主屏上。
上图是右侧显示不完整的情况。
2、修改plugin项目中的tgtsmlplatforminputcontext.cpp文件中的void TgtsmlPlatformInputContext::showInputPanel()中的代码,如下:
void TgtsmlPlatformInputContext::showInputPanel()
{
if(!m_keyboard){
m_keyboard = new KeyboardForm;
connect(m_keyboard, &KeyboardForm::sendKeyToFocusItem, this, &TgtsmlPlatformInputContext::sendKeyToFocusItem);
}
if(m_keyboard->isHidden())m_keyboard->show();
QWidget *widgetTmp = qobject_cast<QWidget*>(m_focusitem);
if(widgetTmp){
//注释以下代码,因为没有考虑扩展屏幕的坐标问题
// QPoint widgetGlobalPos = widgetTmp->mapToGlobal(QPoint(0, 0));
// if(widgetGlobalPos.x() < 0){
// widgetGlobalPos.setX(0);
// }
// if(widgetGlobalPos.y() < 0){
// widgetGlobalPos.setY(0);
// }
// if(qApp->desktop()->width() - widgetGlobalPos.x() < m_keyboard->width()){
// widgetGlobalPos.setX(qApp->desktop()->width() - m_keyboard->width());
// }
// if(qApp->desktop()->height() - widgetGlobalPos.y() - 30 < m_keyboard->height()){
// widgetGlobalPos.setY(widgetGlobalPos.y() - m_keyboard->height() - 10);
// }
// else{
// widgetGlobalPos = widgetGlobalPos + QPoint(0,30);
// }
// m_keyboard->move(widgetGlobalPos);
//改为以下代码,增加考虑扩展屏幕的代码
//获取当前屏幕及屏幕几何矩形坐标
int currentScreen = qApp->desktop()->screenNumber(widgetTmp);
QScreen *screen = QGuiApplication::screens().at(currentScreen);
QRect rect = screen->geometry();
QPoint widgetGlobalPos = widgetTmp->mapToGlobal(QPoint(0, 0));
if(widgetGlobalPos.x() < rect.x()) {
widgetGlobalPos.setX(rect.x());
}
if (widgetGlobalPos.y() < rect.y())
{
widgetGlobalPos.setY(rect.y());
}
if(rect.width() - widgetGlobalPos.x() < m_keyboard->width()) {
widgetGlobalPos.setX(rect.width() - m_keyboard->width());
}
if(rect.height() - widgetGlobalPos.y() - 30 < m_keyboard->height()) {
widgetGlobalPos.setY(widgetGlobalPos.y() - m_keyboard->height() - 10);
}
else {
widgetGlobalPos = widgetGlobalPos + QPoint(0,30);
}
m_keyboard->move(widgetGlobalPos);
}
}
3、修改后重新编译、重新部署,再运行demo程序就正常了。