银河麒麟系统中Qt程序无法切换中文,编译fcitx-qt5出现问题,输入法插件库libfcitxplatforminputcontextplugin.so

银河麒麟系统中Qt程序无法切换中文

1.环境
  1. 操作系统:银河麒麟

  2. CPU:飞腾2000

  3. 开发环境:QT5.9.9

  4. 输入法:搜狗输入法

2.问题

在银河麒麟系统中,基于QT5.9.9版本,使用Qt Creator开发的桌面应用程序,启动后,在应用编辑框(QTextEdit)无法输入中文,切换输入法无效。

编译fcitx-qt5,cmake时报ECM 、XKBCommon、bison-3.0.4错误。

make时报error: no matching function for call to ‘QMetaObject::invokeMethod(QFcitxPlatformInputContext*, QFcitxPlatformInputContext::setFocusObject(QObject*)::<lambda()>, Qt::ConnectionType)’
304 | Qt::QueuedConnection)错误。

3.原因分析

linux内核系统,包含了银河麒麟系统(基于linux内核),QT程序需要切换输入法(中文),依赖于QT输入法插件。

window版本QT安装时会自动安装window版本的输入法插件,linux版本QT安装时不一定安装该系统的输入法插件,至少银河麒麟系统不会安装。

4.QT安装环境描述

在银河麒麟系统环境下,QT只能通过源码编译安装。

本人QT输入法插件安装路径:

安装路径:/usr/local/Qt-5.9.9-release/plugins/platforminputcontexts

本人QT输入法插件:

libcomposeplatforminputcontextplugin.so

libibusplatforminputcontextplugin.so

libqtvirtualkeyboardplugin.so

插件目录中缺少libfcitxplatforminputcontextplugin.so插件,该插件对银河麒麟系统中QT程序中文输入法切换提供了支撑,因此,我们要获取该插件。

5.中文输入法插件注意点

重点:版本要一致。

QT程序:如果QT程序是V5.9.9版本编译的,输入法插件编译安装也必须基于V5.9.9版本(输入法插件编译安装依赖于QT版本),两者保持一致。

Qt Creator开发工具:开发过程中需要切换输入法,也需libfcitxplatforminputcontextplugin.so插件支持,才能使用中文输入法,Qt Creator也是基于QT某版本,因此,Qt Creator和输入法插件依赖的QT版本保持一致。

6.操作系统环境

银河麒麟系统部分UI功能是依赖于QT的,因此银河麒麟系统本身安装有QT版本,本人操作系统本身安装有QT5.12.12版本,安装的Qt Creator基于QT5.12.12版本,系统安装的QT5.12.12版本中包含了libfcitxplatforminputcontextplugin.so插件(该插件基于QT5.12.12),因此本人Qt Creator可以输入中文,这也回答了上面的版本一致问题(Qt Creator和输入法插件依赖的QT保本保持一致),该插件位置在/usr/lib/aarch64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so。

7.回答网上部分解决方案
  1. 网上有部分技术人员说,将该/usr/lib/aarch64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so(每个人目录可能不一样,可以使用find / -name libfcitxplatforminputcontextplugin.so查找)插件拷贝到自己安装的QT插件目录、Qt Creator插件目录、QT程序插件目录中,修改一下插件执行权限就可以输入中文,里面有很大歧义,如果QT程序、Qt Creator和插件依赖的QT版本一致,则可以切换输入法,如果版本不一致,还是无法解决问题
  2. 网上有部分技术人员说,执行sudo apt-get install fcitx-qt5,这个也只能解决QT程序、Qt Creator和插件依赖的QT版本一致,如果不一致,可能只能解决Qt Creator中文输入法问题,无法解决QT程序问题,因为sudo apt-get install fcitx-qt5命令会将一些依赖库安装到系统路径下,安装的最新版插件库,与实际使用QT版本不一致。
8.解决方案

基于QT5.9.9版本,手动编译fcitx-qt5,fcitx-qt5提供了对linux环境中文输入法支持,编译成功后会生成libfcitxplatforminputcontextplugin.so插件。

以下路径都是本人的,可以根据自己情况进行更改。

8.1下载fcitx-qt5源码

因为fcitx-qt5官网有源码,但是版本太多,不知道选择哪个,所以从git上下载最新源码。

新建一个文件夹/home/adminyw/soft/fcitx,在/fcitx/文件夹下使用终端执行以下语句,会将源码下载到当前文件夹下的fcitx-qt5文件夹中,有时候外网不稳定,可以多执行几次:

adminyw@adminyw-pc:~/soft/fcitx$ git clone https://github.com/fcitx/fcitx-qt5

下载内容如下:

adminyw@adminyw-pc:~/soft/fcitx/fcitx-qt5$ ll

总用量 76
drwxrwxr-x 7 adminyw adminyw 4096 2月 21 14:24 ./
drwxrwxr-x 3 adminyw adminyw 4096 2月 21 14:00 …/
-rw-rw-r-- 1 adminyw adminyw 1754 2月 21 14:01 .clang-format
-rwxrwxr-x 1 adminyw adminyw 150 2月 21 14:01 clang-format.sh*
drwxrwxr-x 2 adminyw adminyw 4096 2月 21 14:01 cmake/
-rw-rw-r-- 1 adminyw adminyw 1643 2月 21 14:01 CMakeLists.txt
-rw-rw-r-- 1 adminyw adminyw 17989 2月 21 14:01 COPYING
-rw-rw-r-- 1 adminyw adminyw 1488 2月 21 14:01 COPYING.BSD
-rw-rw-r-- 1 adminyw adminyw 158 2月 21 14:01 .formatignore
drwxrwxr-x 8 adminyw adminyw 4096 2月 21 14:01 .git/
-rw-rw-r-- 1 adminyw adminyw 80 2月 21 14:01 .gitignore
drwxrwxr-x 2 adminyw adminyw 4096 2月 21 14:01 po/
drwxrwxr-x 7 adminyw adminyw 4096 2月 21 14:01 qt5/
drwxrwxr-x 3 adminyw adminyw 4096 2月 21 14:01 qt6/
-rw-rw-r-- 1 adminyw adminyw 141 2月 21 14:01 README

8.2CMakeLists配置
  1. 要求cmake版本高于VERSION 3.1;
  2. 要求QT版本高于REQUIRED_QT_VERSION 5.1.0;
  3. 需要ECM 1.4.0模块、XKBCommon 0.5.0模块、bison-3.0.4模块;
  4. 关于编译的QT版本,option(ENABLE_QT5 “Enable Qt5” On)、option(ENABLE_QT6 “Enable Qt6 im module” Off),默认配置是按QT5版本进行编译,如果想用QT6版本编译,需将QT5的on设置为false,QT6的off设置为on。
    以上是CMakeLists中需要注意的点,同时也是cmake和编译fcitx-qt5前提条件
8.3安装必要依赖
  1. 该库是通过cmake构建的,需要安装cmake,执行sudo apt-get install cmake(会将cmake安装到系统中,不用自己设置环境变量),也可下载linux版本的cmake,解压后,将bin目录设置到PATH中,版本高于3.1;

  2. 安装extra-cmake-modules-1.4.0,即ECM 模块,下载该源码,解压后目录/home/adminyw/soft/fcitx/extra-cmake-modules-1.4.0,在该路径终端分别执行:mkdir build,cd build,cmake …,make,sudo make install,解决cmake时报缺失ECM 问题;

  3. 如果cmake和make时不报XKBCommon的错误,可以不安装XKBCommon和bison,如果报XKBCommon错误,先安装bison,再安装XKBCommon。下载bison-3.0.4和libxkbcommon-0.5.0源码,解压后,进入解压目录,在该路径终端分别执行./configure,make,sudo make install,解决cmake时缺失xkbcommon问题。

8.4执行cmake

在/home/adminyw/soft/fcitx/fcitx-qt5路径,打开终端,执行以下语句:

adminyw@adminyw-pc:~/soft/fcitx/fcitx-qt5$ mkdir build
adminyw@adminyw-pc:~/soft/fcitx/fcitx-qt5$ cd build
adminyw@adminyw-pc:~/soft/fcitx/fcitx-qt5$ cmake .. -DENABLE_LIBRARY=false -DQt5Concurrent_DIR=/usr/local/Qt-5.9.9-release/lib/cmake/Qt5Concurrent -DQt5Core_DIR=/usr/local/Qt-5.9.9-release/lib/cmake/Qt5Core -DQt5DBus_DIR=/usr/local/Qt-5.9.9-release/lib/cmake/Qt5DBus -DQt5Gui_DIR=/usr/local/Qt-5.9.9-release/lib/cmake/Qt5Gui -DQt5Widgets_DIR=/usr/local/Qt-5.9.9-release/lib/cmake/Qt5Widgets -DQt5_DIR=/usr/local/Qt-5.9.9-release/lib/cmake/Qt5

说明:-DENABLE_LIBRARY=false:解决Fcitx 4.2.8、LibIntl 、po报错问题;

-DQt5Concurrent_DIR、-DQt5Core_DIR、-DQt5DBus_DIR、-DQt5Gui_DIR、-DQt5Widgets_DIR、-DQt5_DIR:基于自己QT5.9.9版本进行编译,如果不设置,则以操作系统QT5.12.12版本进行编译,这样得到输入法插件将版本不一致,无法使用。网上有朋友说将自己安装的QT的bin目录设置到PATH路径下,但我设置了,还是无法解决编译时以QT5.12.12版本进行编译。

执行cmake后,显示以下信息,说明cmake成功

-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") 
-- Found XKBCommon_XKBCommon: /usr/lib/aarch64-linux-gnu/libxkbcommon.so (found version "0.10.0") 
-- Found XKBCommon: /usr/lib/aarch64-linux-gnu/libxkbcommon.so (found suitable version "0.10.0", minimum required is "0.5.0") found components: XKBCommon 
-- The following OPTIONAL packages have been found:

 * PkgConfig

-- The following REQUIRED packages have been found:

 * ECM (required version >= 1.4.0)
 * XKBCommon (required version >= 0.5.0), Keyboard handling library using XKB data, <http://xkbcommon.org>
 * Qt5DBus
 * Qt5Widgets
 * Qt5Concurrent
 * Qt5 (required version >= 5.1.0)
 * Qt5Gui (required version >= 5.1.0)
 * Qt5Core

-- Configuring done
-- Generating done
-- Build files have been written to: /home/adminyw/soft/fcitx/fcitx-qt5/build
8.5执行make

fcitx-qt5基于QT版本,我下载是最新fcitx-qt5源码,最新的fcitx-qt5代码发生改变,支持Qt5.9以上版本,Qt5.9.9版本中qobjectdefs.h的invokeMethod不支持lambda函数,Qt5.9以后版本支持lambda表达式,
fcitx-qt5中的QFcitxPlatformInputContext.cpp,在代码块中调用了

QMetaObject::invokeMethod(
            this,
            [this, window]() {
                if (window != m_lastWindow) {
                    return;
                }
                if (validICByWindow(window.data())) {
                    cursorRectChanged();
                }
            },
            Qt::QueuedConnection);

此方法中使用了lambda表达式,再使用Qt5.9.9版本编译fcitx-qt5时会出现问题,因为QT5.9.9中qobjectdefs.h不提供有lambda表达式参数的接口,应该QT5.9版本以后提供该接口,因此需要修改fcitx-qt5中的源码,去掉lambda表达式写法,换做slots槽函数。

修改qfcitxplatforminputcontext.h,修改如下:

private Q_SLOTS:
    void processKeyEventFinished(QDBusPendingCallWatcher *);
    //增加槽函数,使fcitx-qt5源码适配QT5.9.9版本
    void cursorRectChangedForOldQtVersion(QPointer<QWindow> window);

修改qfcitxplatforminputcontext.cpp中的setFocusObject方法,如下:

void QFcitxPlatformInputContext::setFocusObject(QObject *object) {
    Q_UNUSED(object);
    FcitxInputContextProxy *proxy = validICByWindow(m_lastWindow);
    commitPreedit(m_lastObject);
    if (proxy) {
        proxy->focusOut();
    }

    QWindow *window = qApp->focusWindow();
    m_lastWindow = window;
    m_lastObject = object;
    // Always create IC Data for window.
    if (window) {
        proxy = validICByWindow(window);
        if (!proxy) {
            createICData(window);
        }
    }
    if (!window || (!inputMethodAccepted() && !objectAcceptsInputMethod())) {
        m_lastWindow = nullptr;
        m_lastObject = nullptr;
        return;
    }
    if (proxy) {
        proxy->focusIn();
        // We need to delegate this otherwise it may cause self-recursion in
        // certain application like libreoffice.
        auto window = m_lastWindow;
        //注释该方法的调用,QT5.9.9不支持lambda表达式参数的接口,invokeMethod方法由qobjectdefs.h提供
//        QMetaObject::invokeMethod(
//            this,
//            [this, window]() {
//                if (window != m_lastWindow) {
//                    return;
//                }
//                if (validICByWindow(window.data())) {
//                    cursorRectChanged();
//                }
//            },
//            Qt::QueuedConnection);
        //修改为该方法调用,"cursorRectChangedForOldQtVersion"是qfcitxplatforminputcontext.h中新增函数名
        QMetaObject::invokeMethod(
                    this,
                    "cursorRectChangedForOldQtVersion",
                    Qt::QueuedConnection,
                    Q_ARG(QPointer<QWindow>, window));
    }
}

不按上面要求修改源码,make时会报错:

/home/adminyw/soft/fcitx/fcitx-qt5/qt5/platforminputcontext/qfcitxplatforminputcontext.cpp: In member function ‘virtual void QFcitxPlatformInputContext::setFocusObject(QObject*)’:
/home/adminyw/soft/fcitx/fcitx-qt5/qt5/platforminputcontext/qfcitxplatforminputcontext.cpp:304:33: error: no matching function for call to ‘QMetaObject::invokeMethod(QFcitxPlatformInputContext*, QFcitxPlatformInputContext::setFocusObject(QObject*)::<lambda()>, Qt::ConnectionType)304 |             Qt::QueuedConnection);
      |                                 ^
In file included from /usr/local/Qt-5.9.9-release/include/QtCore/qmetatype.h:49,
                 from /usr/local/Qt-5.9.9-release/include/QtDBus/qtdbusglobal.h:44,
                 from /usr/local/Qt-5.9.9-release/include/QtDBus/qdbusconnection.h:44,
                 from /usr/local/Qt-5.9.9-release/include/QtDBus/QDBusConnection:1,
                 from /home/adminyw/soft/fcitx/fcitx-qt5/qt5/platforminputcontext/qfcitxplatforminputcontext.cpp:21:
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:406:17: note: candidate: ‘static bool QMetaObject::invokeMethod(QObject*, const char*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument)406 |     static bool invokeMethod(QObject *obj, const char *member,
      |                 ^~~~~~~~~~~~
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:406:17: note:   candidate expects 14 arguments, 3 provided
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:420:24: note: candidate: ‘static bool QMetaObject::invokeMethod(QObject*, const char*, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument)420 |     static inline bool invokeMethod(QObject *obj, const char *member,
      |                        ^~~~~~~~~~~~
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:420:63: note:   no known conversion for argument 2 from ‘QFcitxPlatformInputContext::setFocusObject(QObject*)::<lambda()>’ to ‘const char*’
  420 |     static inline bool invokeMethod(QObject *obj, const char *member,
      |                                                   ~~~~~~~~~~~~^~~~~~
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:437:24: note: candidate: ‘static bool QMetaObject::invokeMethod(QObject*, const char*, Qt::ConnectionType, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument)437 |     static inline bool invokeMethod(QObject *obj, const char *member,
      |                        ^~~~~~~~~~~~
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:437:63: note:   no known conversion for argument 2 from ‘QFcitxPlatformInputContext::setFocusObject(QObject*)::<lambda()>’ to ‘const char*’
  437 |     static inline bool invokeMethod(QObject *obj, const char *member,
      |                                                   ~~~~~~~~~~~~^~~~~~
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:454:24: note: candidate: ‘static bool QMetaObject::invokeMethod(QObject*, const char*, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument)454 |     static inline bool invokeMethod(QObject *obj, const char *member,
      |                        ^~~~~~~~~~~~
/usr/local/Qt-5.9.9-release/include/QtCore/qobjectdefs.h:454:63: note:   no known conversion for argument 2 from ‘QFcitxPlatformInputContext::setFocusObject(QObject*)::<lambda()>’ to ‘const char*’
  454 |     static inline bool invokeMethod(QObject *obj, const char *member,
      |                                                   ~~~~~~~~~~~~^~~~~~
/usr/bin/cmake: /home/adminyw/soft/dminstall/bin/libcurl.so.4: no version information available (required by /usr/bin/cmake)
[ 85%] Building CXX object qt5/platforminputcontext/CMakeFiles/fcitxplatforminputcontextplugin.dir/inputcontext1proxy.cpp.o
/usr/bin/cmake: /home/adminyw/soft/dminstall/bin/libcurl.so.4: no version information available (required by /usr/bin/cmake)
[ 90%] Building CXX object qt5/platforminputcontext/CMakeFiles/fcitxplatforminputcontextplugin.dir/inputmethodproxy.cpp.o
make[2]: *** [qt5/platforminputcontext/CMakeFiles/fcitxplatforminputcontextplugin.dir/build.make:159:qt5/platforminputcontext/CMakeFiles/fcitxplatforminputcontextplugin.dir/qfcitxplatforminputcontext.cpp.o] 错误 1
make[2]: *** 正在等待未完成的任务....
make[1]: *** [CMakeFiles/Makefile2:113:qt5/platforminputcontext/CMakeFiles/fcitxplatforminputcontextplugin.dir/all] 错误 2
make: *** [Makefile:130:all] 错误 2

修改完成后,执行以下语句:

adminyw@adminyw-pc:~/soft/fcitx/fcitx-qt5/build$ make -j4

编译成功后,会在/home/adminyw/soft/fcitx/fcitx-qt5/build/qt5/platforminputcontext文件夹下生成libfcitxplatforminputcontextplugin.so输入法插件库,该库就是基于QT5.9.9版本编译后的插件库,然后将该库拷贝到自己安装的QT插件目录、Qt Creator插件目录、QT程序插件目录中,修改一下插件执行权限就可以切换输入法,使用中文进行输入。

8.6执行make install

无必要,可以不执行make install,因为make后会生成libfcitxplatforminputcontextplugin.so插件库,可以执行使用。

make install是将fcitx-qt5安装到/usr/local/目录下,也会生成插件库,会将相关信息添加环境变量中。

9.总结

fcitx-qt5编译安装,一定要注意QT版本问题。

以上总结都是个人编译过程遇到问题,如果为的解答没有解决您的问题,可以参考其他linux或银河麒麟系统无法输入中文的解决方案,和我的进行结合,解决个人问题。

如果还是没有解决,欢迎评论区留言,共同讨论,谢谢大家阅读交流。

  • 17
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值