QT 使用自定义输入法

在Linux root环境下,由于无法使用fcitx输入法框架,本文介绍了如何在QT中使用自定义输入法,包括编译googlepinyin静态库,编译插件,加载插件,连接信号与槽以及修改插件的详细步骤。此外,还提到了一个由tgtsml编写的Qt5输入法实现的GitHub资源。

QT 使用自定义输入法


因在Linux中,root环境下无法使用fcitx输入法框架,也就无法使用输入法,这个时候只好使用自己定义的输入法,这样,即使是在root下,也能输入中文。

1 使用插件


1)编译googlepinyin静态库

QT          -= gui
TEMPLATE    = lib

CONFIG      += staticlib
TARGET      = googlepinyin
win32{
    CONFIG      += debug_and_release build_all
    CONFIG(debug, debug|release){
        TARGET  = ../../plugin/googlepinyin/$$join(TARGET,,,d)
    }
    CONFIG(release, debug|release){
        TARGET  = ../../plugin/googlepinyin/$$TARGET
    }
}
unix{
    TARGET      = ../plugin/googlepinyin/$$TARGET
    MOC_DIR     = ../tmpfiles
    RCC_DIR     = ../tmpfiles
    UI_DIR      = ../tmpfiles
    OBJECTS_DIR = ../tmpfiles
}

编译得到libgooglepinyin.a静态库。

2)编译plugin

将上一步编译获得的libgooglepinyin.a放到plugin项目的googlepinyin目录下,开始编译。

QT          = core gui-private widgets

TEMPLATE    = lib
TARGET      = tgtsmlInputContextPlugin

INCLUDEPATH += $$PWD/googlepinyin

win32{
    CONFIG      += debug_and_release build_all

    CONFIG(debug, debug|release){
        TARGET  = ../../debug/platformInputContexts/$$join(TARGET,,,d)
        LIBS    += -L$$PWD/googlepinyin/ -lgooglepinyind
    }CONFIG(release, debug|release){
        TARGET  = ../../release/platformInputContexts/$$TARGET
        LIBS    += -L$$PWD/googlepinyin/ -lgooglepinyin
    }
}
unix{
    TARGET      = ../target/$$TARGET
    LIBS        += -L$$PWD/googlepinyin/ -lgooglepinyin
    MOC_DIR     = ../tmpfiles
    RCC_DIR     = ../tmpfiles
    UI_DIR      = ../tmpfiles
    OBJECTS_DIR = ../tmpfiles
}

获得插件libtgtsmlInputContextPlugin.so

3)加载插件

./dict目录下放置两个dat词典文件;
.pro中添加相应库;

LIBS += -L./plugins -ltgtsmlInputContextPlugin

widget.h添加成员变量及LoadPlugins()方法;

bool LoadPlugins();

TgtsmlPlatformInputContext *m_input_chinese;

widget.cpp

bool NewPatientPage::LoadPlugins()
{
    QString pluginpath("./plugins/libtgtsmlInputContextPlugin.so");
    QFile file("./plugins/libtgtsmlInputContextPlugin.so");
    if (!file.exists())
    {
        QMessageBox::warning(this,tr("错误信息"),tr("找不到%1文件").arg(pluginpath));
        return false;
    }
    QPluginLoader loader(pluginpath);
    QObject *instance = loader.instance(); 
    if (instance!= nullptr)
    {
        qDebug()<<pluginpath+" is loaded";
        TgtsmlPlatformInputContextPlugin *avc = qobject_cast<TgtsmlPlatformInputContextPlugin *>(instance);
        m_input_chinese =  avc->create("tgtsml",QStringList());
        return true;
    }
    else {
        QMessageBox::information(this,"failed to load Chinese input plugin",loader.errorString());
    }
    // 需要手动释放
    delete instance;
    return true;
}

4)连接相应的信号与槽

重载QLineEditLineEdit.h

class LineEdit : public QLineEdit
{
    Q_OBJECT
public:
    LineEdit(QWidget* parent=nullptr);
    virtual ~LineEdit()=default;

signals:
    void SendObject(QObject *obj);
    void showInputPanel();
    void hideInputPanel();
    void KeyPress(QKeyEvent *e);

protected:
    virtual void focusInEvent(QFocusEvent*e);
    virtual void focusOutEvent(QFocusEvent*e);
    virtual void keyPressEvent(QKeyEvent *e);
    virtual void mousePressEvent(QMouseEvent*e);
};

LineEdit.cpp

#include "LineEdit.h"
//---------------------------------
LineEdit::LineEdit(QWidget *parent)
    :QLineEdit(parent)
{
}
//---------------------------------
void LineEdit::focusInEvent(QFocusEvent *e)
{
    emit SendObject(this);
//    emit showInputPanel();
    return QLineEdit::focusInEvent(e);
}

void LineEdit::focusOutEvent(QFocusEvent *e)
{
    emit hideInputPanel();
    return QLineEdit::focusOutEvent(e);
}

//---------------------------------
void LineEdit::keyPressEvent(QKeyEvent *e)
{
    if(e->key()==Qt::Key_Backspace){
        if(e->modifiers().testFlag(Qt::NoModifier)){
            emit KeyPress(e);
            return;
        }
        else if(e->modifiers().testFlag(Qt::ShiftModifier)){
            return;
        }else if(e->modifiers().testFlag(Qt::ControlModifier)){
            QKeyEvent *p= new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
            QLineEdit::keyPressEvent(p);
            return;
        }
    }

    emit KeyPress(e);

    QLineEdit::keyPressEvent(e);

    if((e->key()>=Qt::Key_A && e->key()<=Qt::Key_Z) || (e->key()>=Qt::Key_1 && e->key()<=Qt::Key_5) ){
        QKeyEvent *p= new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
        QLineEdit::keyPressEvent(p);
    }
    switch (e->key()){
    case Qt::Key_Comma: case Qt::Key_Period: case Qt::Key_Slash: case Qt::Key_Space:
    case Qt::Key_Minus : case Qt::Key_Equal:
        QKeyEvent *p= new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
        QLineEdit::keyPressEvent(p);
        break;
    }
}
//---------------------------------
void LineEdit::mousePressEvent(QMouseEvent *e)
{
    emit showInputPanel();
    return QLineEdit::mousePressEvent(e);
}

widget.cpp

    connect(m_edit["doctor"], SIGNAL(SendObject(QObject*)), m_input_chinese, SLOT(setFocusObject(QObject *)));
    connect(m_edit["doctor"], SIGNAL(showInputPanel()), m_input_chinese, SLOT(showInputPanel()));
    connect(m_edit["doctor"], SIGNAL(hideInputPanel()), m_input_chinese, SLOT(hideInputPanel()));
    connect(m_edit["doctor"], SIGNAL(KeyPress(QKeyEvent *)), m_input_chinese, SLOT(KeyPress(QKeyEvent *)));

5)修改插件

修改KeyboardForm.h

#include "keyboardform.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFontDatabase>
#include <QFile>
#include <QDebug>
#include <QApplication>
#include <QMouseEvent>
#include "pinyinime.h"

#include <iostream>

using std::initializer_list;
//using std::pair;
using namespace ime_pinyin;

#define chinesecharacters_number    7
const char *keyboard_characters = "qwertyuiopasdfghjklzxcvbnm,.?";
const QString keyboard_symbols[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
                                   "@", "#", "_", "\"", "“", "”", ",", ",", ".", "。",
                                   ";", ";", ":", ":", "'", "’", "、", "!", "!",
                                   "~", "~", "+", "-", "*", "/", "=", "÷", "×", "√",
                                   "`", "?", "^", "&&", "%", "|", "(", ")", "(", ")",
                                   "[", "]", "【", "】", "{", "}", "<", ">", "《",
                                   "》", "$", "€", "£", "¢", "¥", "§", "—", "/", "\",
                                   "·", "……", "——", "→", "←", "↑", "↓", "■", "□", "●",
                                   "○", "『", "』", "「", "」", "★", "☆", "◆", "◇"}; //29*3

KeyboardForm::KeyboardForm(QWidget *parent)
    : QWidget(parent)
{
    character_btns_list.clear();
    current_mode = InputMode::en;
    upper_mode = false;
    m_symbol_page = 0;

    this->setFixedSize(800,250);
    int keyboard_btn_width = this->width()/11.5;
    int keyboard_btn_height = this->height()/5.0;

    //设置主窗体样式
    this->setAttribute(Qt::WA_TranslucentBackground);
    this->setWindowFlags(Qt::Tool | \
                         Qt::FramelessWindowHint | \
                         Qt::WindowStaysOnTopHint | \
                         Qt::WindowDoesNotAcceptFocus);

    //加载QSS样式表
    QFile qss(":/styles/res/stylesheet.qss");
    if(false == qss.open(QFile::ReadOnly))return;
    this->setStyleSheet(qss.readAll());
    qss.close();

    //图标字体
    int fontId = QFontDatabase::addApplicationFont(":/font/res/FontAwesome.otf");
    QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0);
    QFont btnicofont(fontName);
    btnicofont.setPixelSize(10);

    //单行布局
    QHBoxLayout *hb[6];
    for(int i=0; i<6; i++)
    {
        hb[i] = new QHBoxLayout();
        hb[i]->setMargin(0);
        i == 1 ? hb[i]->setSpacing(2) : hb[i]->setSpacing(0);
    }

    widget_pinyin = new QWidget(this);
    widget_pinyin->setFixedHeight(keyboard_btn_height);
    //拼音缓存
    m_label_pinyin = new QLabel(this);
    m_label_pinyin->setFixedHeight(keyboard_btn_height*0.4);
    hb[0]->addWidget(m_label_pinyin);
    hb[0]->addStretch(1);

    //汉子缓存
    for(int i=0; i<chinesecharacters_number; i++)
    {
        QPushButton *btn = new QPushButton(this);
        btn->setFixedHeight(keyboard_btn_height*0.6);
        hb[1]->addWidget(btn);
        if(i != chinesecharacters_number - 1) hb[1]->addStretch(1);
        if (i == 0 || i == chinesecharacters_number-1)
        {
            change_chinese_characters_page_list.append(btn);
            btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
            btn->setFont(btnicofont);
            btn->setText(i == 0 ? QString(QChar(0xf0d9)) : QString(QChar(0xf0da)));
            btn->setObjectName("hanzichangepage");
            i == 0 ? \
            connect(btn, &QPushButton::clicked, this, &KeyboardForm::chineseCharactersUpdatePrevious) :
            connect(btn, &QPushButton::clicked, this, &KeyboardForm::chineseCharactersUpdateNext);
        }
        else
        {
            chinese_characters_list.append(btn);
            btn->setObjectName("hanzicandidates");
            connect(btn, &QPushButton::clicked, this, &KeyboardForm::chineseCharactersSelected);
        }
    }

    QVBoxLayout *vb_pinyin = new QVBoxLayout(widget_pinyin);
    vb_pinyin->addLayout(hb[0]);
    vb_pinyin->addLayout(hb[1]);
    vb_pinyin->setMargin(0);
    vb_pinyin->setSpacing(0);

    widget_keyboard = new QWidget(this);
    widget_keyboard->setFixedHeight(keyboard_btn_height*4.0);
    //键盘
    for(int i=0; i<29; i++)
    {
        QPushButton *btn = new QPushButton(QChar(keyboard_characters[i]),this);
        btn->setFixedSize(keyboard_btn_width, keyboard_btn_height);
        character_btns_list.append(btn);
        connect(btn, &QPushButton::clicked, this, &KeyboardForm::characterButtonClicked);
    }
    //第一排字母:0-9
    for(int i=0; i<10; i++)
    {
        hb[2]->addWidget(character_btns_list.at(i));
    }
    QPushButton *btn_backspace = new QPushButton(QChar(0xf060));
    btn_backspace->setFont(btnicofont);
    btn_backspace->setFixedSize(keyboard_btn_width*1.5, keyboard_btn_height);
    btn_backspace->setObjectName("function_button");
    hb[2]->addWidget(btn_backspace);
    connect(btn_backspace, &QPushButton::clicked, this, &KeyboardForm::btnBackspaceClicked);
    //第二排字母:10-18
    hb[3]->addStretch(1);
    for(int i=10; i<19; i++)
    {
        hb[3]->addWidget(character_btns_list.at(i));
    }
    QPushButton *btn_enter = new QPushButton("Enter");
    btn_enter->setFixedSize(keyboard_btn_width*1.5, keyboard_btn_height);
    btn_enter->setObjectName("function_button");
    hb[3]->addWidget(btn_enter);
    hb[3]->addStretch(1);
    connect(btn_enter, &QPushButton::clicked, this, &KeyboardForm::btnEnterClicked);
    //第三排字母:20-26
    QPushButton *btn_upper = new QPushButton(QChar(0xf062));
    btn_upper->setFixedSize(keyboard_btn_width*1.5, keyboard_btn_height);
    btn_upper->setFont(btnicofont);
    btn_upper->setObjectName("function_button");
    hb[4]->addWidget(btn_upper);
    connect(btn_upper, &QPushButton::clicked, this, &KeyboardForm::btnUpperClicked);
    for(int i=19; i<29; i++)
    {
        hb[4]->addWidget(character_btns_list.at(i));
    }
    character_btns_list.append(btn_upper);
    //第四排功能键
    btn_symbols = new QPushButton(".?123");
    btn_symbols->setFixedSize(keyboard_btn_width*1.5, keyboard_btn_height);
    btn_symbols->setObjectName("function_button");
    hb[5]->addWidget(btn_symbols);
    connect(btn_symbols, &QPushButton::clicked, this, &KeyboardForm::btnSymbolsClicked);
    btn_language = new QPushButton(QChar(0xf0ac));
    btn_language->setFixedSize(keyboard_btn_width, keyboard_btn_height);
    btn_language->setFont(btnicofont);
    btn_language->setObjectName("function_button");
    hb[5]->addWidget(btn_language);
    connect(btn_language, &QPushButton::clicked, this, &KeyboardForm::btnLanguageClicked);
    btn_blankspace = new QPushButton("English");
    btn_blankspace->setFixedHeight(keyboard_btn_height);
    hb[5]->addWidget(btn_blankspace);
    character_btns_list.append(btn_blankspace);
    connect(btn_blankspace, &QPushButton::clicked, this, &KeyboardForm::btnBlankspaceClicked);
    QPushButton *btn_emoji = new QPushButton(QChar(0xf118));
    btn_emoji->setFixedSize(keyboard_btn_width, keyboard_btn_height);
    btn_emoji->setFont(btnicofont);
    btn_emoji->setObjectName("emoji");
    hb[5]->addWidget(btn_emoji);
    connect(btn_emoji, &QPushButton::clicked, this, &KeyboardForm::btnEmojiClicked);
    QPushButton *btn_hidekeyboard = new QPushButton(QString(QChar(0xf11c)).append(QChar(0xf103)));
    btn_hidekeyboard->setFixedSize(keyboard_btn_width*1.5, keyboard_btn_height);
    btn_hidekeyboard->setFont(btnicofont);
    btn_hidekeyboard->setObjectName("function_button");
    hb[5]->addWidget(btn_hidekeyboard);
    connect(btn_hidekeyboard, &QPushButton::clicked, this, &KeyboardForm::hideKeyboard);

    QVBoxLayout *vb_keyboard = new QVBoxLayout(widget_keyboard);
    vb_keyboard->setMargin(0);
    vb_keyboard->setSpacing(0);
    for(int i=2; i<6; i++)
    {
        vb_keyboard->addLayout(hb[i]);
    }

    QVBoxLayout *vb_system = new QVBoxLayout(this);
    vb_system->setMargin(0);
    vb_system->setSpacing(0);
    vb_system->addStretch(1);
    vb_system->addWidget(widget_pinyin);
    vb_system->addWidget(widget_keyboard);
    widget_pinyin->hide();

    updateButtonStateOfChineseCharacters();
}

void KeyboardForm::updateButtonStateOfChineseCharacters()
{
    if(m_label_pinyin->text().isEmpty())
    {
        m_label_pinyin->setHidden(true);
        change_chinese_characters_page_list.at(0)->setHidden(true);
        change_chinese_characters_page_list.at(1)->setHidden(true);
    }
    else
    {
        m_label_pinyin->setHidden(false);
        change_chinese_characters_page_list.at(0)->setHidden(false);
        change_chinese_characters_page_list.at(1)->setHidden(false);
    }
}

void KeyboardForm::chineseCharactersUpdatePrevious()
{
    searchChineseCharacters(-1);
}

void KeyboardForm::chineseCharactersUpdateNext()
{
    searchChineseCharacters(1);
}

void KeyboardForm::chineseCharactersSelected()
{
    emit sendKeyToFocusItem(((QPushButton*)sender())->text());
    clearChineseCache();
}

void KeyboardForm::btnBackspaceClicked(bool boo)
{
    if(current_mode != InputMode::zh || m_label_pinyin->text().isEmpty())
    {
        if(!boo){
            emit sendKeyToFocusItem("\x7F");
        }
    }
    else
    {
		emit sendKeyToFocusItem("\x01");
        m_label_pinyin->setText(m_label_pinyin->text().left(m_label_pinyin->text().length()-1));
        if(m_label_pinyin->text().isEmpty())
        {
            clearChineseCache();
        }
        else
        {
            searchChineseCharacters(0);
        }
    }
}

void KeyboardForm::btnEnterClicked(bool boo)
{
    if(current_mode != InputMode::zh || m_label_pinyin->text().isEmpty())
    {
        emit sendKeyToFocusItem("\n");
    }
    else
    {
        emit sendKeyToFocusItem(m_label_pinyin->text());
        clearChineseCache();
    }
}

void KeyboardForm::btnUpperClicked()
{
    if(current_mode == InputMode::en)
    {
        upper_mode = !upper_mode;
    }
    else if(current_mode == InputMode::zh)
    {
        if(!m_label_pinyin->text().isEmpty() && m_label_pinyin->text().right(1).compare("'"))
        {
            m_label_pinyin->setText(m_label_pinyin->text().append("'"));
        }
    }
    else
    {
        if(m_symbol_page == 0)
        {
            m_symbol_page = 1;
            character_btns_list.at(character_btns_list.length()-2)->setText("2/3");
        }
        else if(m_symbol_page == 1)
        {
            m_symbol_page = 2;
            character_btns_list.at(character_btns_list.length()-2)->setText("3/3");
        }
        else
        {
            m_symbol_page = 0;
            character_btns_list.at(character_btns_list.length()-2)->setText("1/3");
        }
    }
    updateKeyboard();
}

void KeyboardForm::btnSymbolsClicked()
{
    if(current_mode != InputMode::symb)
    {
        widget_pinyin->setHidden(true);
        if(current_mode == InputMode::en)
        {
            character_btns_list.at(character_btns_list.length()-1)->setText("Symbols");
        }
        else if(current_mode == InputMode::zh)
        {
            character_btns_list.at(character_btns_list.length()-1)->setText("符号");
        }
        ((QPushButton*)sender())->setText("abc");
        last_mode = current_mode;
        current_mode = InputMode::symb;
        character_btns_list.at(character_btns_list.length()-2)->setText("1/3");
    }
    else
    {
        ((QPushButton*)sender())->setText(".?123");
        current_mode = last_mode;
        m_symbol_page = 0;
    }
    upper_mode = false;
    updateKeyboard();
}

void KeyboardForm::btnLanguageClicked()
{
    upper_mode = false;
    if(current_mode == InputMode::zh)
    {
        current_mode = InputMode::en;
    }
    else if(current_mode == InputMode::en)
    {
        current_mode = InputMode::zh;
    }
    if(current_mode != InputMode::symb)
    {
        last_mode = current_mode;
        updateKeyboard();
    }
}

void KeyboardForm::clearChineseCache()
{
    m_label_pinyin->setText("");
    for(int i=0; i<chinese_characters_list.length(); i++)
    {
        chinese_characters_list.at(i)->setText("");
    }
    updateButtonStateOfChineseCharacters();
}

void KeyboardForm::KeyPress(QKeyEvent *e)
{
//    QMap<QString,int> map{{"1",2}};
//    initializer_list<QString> ini={"a","b","c","d","e","f","g","h","i","j","k","l","m",
//        "n","o","p","q","r","s","t","u","v","w","x","y","z"};
//    QVector<QString> vec(ini);
    initializer_list<int> init={10, 23, 21, 12, 2, 13, 14, 15, 7,
        16, 17, 18, 25, 24, 8, 9, 0, 3, 11, 4, 6, 22, 1, 20, 5, 19};
    QVector<int> vect(init);
    switch(e->key()){
    case Qt::Key_Backspace:
        btnBackspaceClicked(true);
        break;
    case Qt::Key_Space:
        btnBlankspaceClicked();
        break;
    case Qt::Key_Return:
        btnEnterClicked(true);
        break;
    case Qt::Key_CapsLock:
        btnUpperClicked();
        break;
    case Qt::Key_Control:
        emit btn_symbols->clicked();
        break;
    case Qt::Key_Alt:
        emit btn_language->clicked();
        break;
    case Qt::Key_Comma:     //,
        emit character_btns_list.at(character_btns_list.length()-5)->clicked();
        break;
    case Qt::Key_Period:    //.
        emit character_btns_list.at(character_btns_list.length()-4)->clicked();
        break;
    case Qt::Key_Slash:     //?
        emit character_btns_list.at(character_btns_list.length()-3)->clicked();
        break;

    default:
        if(e->key()>=Qt::Key_A && e->key()<=Qt::Key_Z){
            emit (character_btns_list.at(vect[e->key()-65]))->clicked();
        }
        else if(e->key()>=Qt::Key_1 && e->key()<=Qt::Key_5){
            if(current_mode == InputMode::zh && !m_label_pinyin->text().isEmpty()){
                emit sendKeyToFocusItem(chinese_characters_list.at(e->key()-49)->text());
                clearChineseCache();
            }else{
                emit sendKeyToFocusItem(QString("%1").arg(e->key()-48));
            }
        }
        break;
    }
}

void KeyboardForm::hideKeyboard()
{
    clearChineseCache();
    this->hide();
}

void KeyboardForm::updateKeyboard()
{
    if(current_mode != InputMode::zh)
    {
        clearChineseCache();
    }
    if(current_mode == InputMode::symb)
    {
        character_btns_list.at(character_btns_list.length()-2)->setCheckable(false);
        for(int i=0; i<29; i++)
        {
            character_btns_list.at(i)->setText(keyboard_symbols[i + m_symbol_page*29]);
        }
    }
    else
    {
        if(true == upper_mode && current_mode == InputMode::en)
        {
            character_btns_list.at(character_btns_list.length()-2)->setCheckable(true);
            character_btns_list.at(character_btns_list.length()-2)->setChecked(true);
            for(int i=0; i<26; i++)
            {
                character_btns_list.at(i)->setText(QChar(keyboard_characters[i]).toUpper());
            }
        }
        else
        {
            character_btns_list.at(character_btns_list.length()-2)->setChecked(false);
            for(int i=0; i<26; i++)
            {
                character_btns_list.at(i)->setText(QChar(keyboard_characters[i]));
            }
        }
        if(current_mode == InputMode::en)
        {
            widget_pinyin->setHidden(true);
            character_btns_list.at(character_btns_list.length()-5)->setText(",");
            character_btns_list.at(character_btns_list.length()-4)->setText(".");
            character_btns_list.at(character_btns_list.length()-3)->setText("?");
            character_btns_list.at(character_btns_list.length()-2)->setText(QChar(0xf062));
            character_btns_list.at(character_btns_list.length()-1)->setText("English");
        }
        else if(current_mode == InputMode::zh)
        {
            character_btns_list.at(character_btns_list.length()-2)->setCheckable(false);
            widget_pinyin->setHidden(false);
            character_btns_list.at(character_btns_list.length()-5)->setText(",");
            character_btns_list.at(character_btns_list.length()-4)->setText("。");
            character_btns_list.at(character_btns_list.length()-3)->setText("?");
            character_btns_list.at(character_btns_list.length()-2)->setText("分词");
            character_btns_list.at(character_btns_list.length()-1)->setText("拼音");
        }
    }
}

void KeyboardForm::btnBlankspaceClicked(bool boo)
{
    if(current_mode != InputMode::zh || m_label_pinyin->text().isEmpty())
    {
        emit sendKeyToFocusItem(" ");
    }
    else
    {
        emit sendKeyToFocusItem(chinese_characters_list.at(0)->text());
        clearChineseCache();
    }
}

void KeyboardForm::btnEmojiClicked()
{
    emit sendKeyToFocusItem(":)");
}

void KeyboardForm::characterButtonClicked()
{
    if(current_mode == InputMode::zh)
    {
        if(((QPushButton*)sender())->text() == "," || ((QPushButton*)sender())->text() == "。" || ((QPushButton*)sender())->text() == "?")
        {
            emit sendKeyToFocusItem(((QPushButton*)sender())->text());
        }
        else
        {
            if(m_label_pinyin->text().length()<15)
            {
                m_label_pinyin->setText(m_label_pinyin->text().append(((QPushButton*)sender())->text()));
                searchChineseCharacters(0);
                updateButtonStateOfChineseCharacters();
            }
        }
    }
    else
    {
        emit sendKeyToFocusItem(((QPushButton*)sender())->text());
    }
}

void KeyboardForm::searchChineseCharacters(const int &currentpage)
{
    const int max_spelling_length = 32;
    const int max_decoded_length = 32;
    const int max_single_hanzi = 20;
    static unsigned int page_change_times = 0;

    QString app_dir(qApp->applicationDirPath()+"/dict");
    im_open_decoder(QString("./dict/dict_pinyin.dat")/*.arg(app_dir)*/.toLocal8Bit().data(),
                    QString("./dict/dict_pinyin_user.dat")/*.arg(app_dir)*/.toLocal8Bit().data());
//    im_open_decoder(QString("/home/robot/01-Wzy-Workspace/07_Work/02_Hip_Replace/QT/Hip_Replacement_6/dict/dict_pinyin.dat").toLocal8Bit().data(),
//                    QString("/home/robot/01-Wzy-Workspace/07_Work/02_Hip_Replace/QT/Hip_Replacement_6/dict/dict_pinyin_user.dat").toLocal8Bit().data());
    im_set_max_lens(max_spelling_length, max_decoded_length);
    im_reset_search();

    QByteArray bytearray(m_label_pinyin->text().toUtf8());
    char *pinyin(bytearray.data());
    size_t cand_num = im_search(pinyin, bytearray.size());

    size_t decode_len;
    im_get_sps_str(&decode_len);
    if (decode_len == 1)
    {
        if (cand_num > 10) cand_num = 10;
    }
    else
    {
        size_t single = 0;
        size_t multi = 0;
        char16 *cand_buf = new char16[max_decoded_length];
        for(size_t i = 0; i < cand_num; i++)
        {
            im_get_candidate(i, cand_buf, max_decoded_length);
            if (strlen((char *)cand_buf) > 2)
            {
                multi++;
            }
            else
            {
                single++;
                if (single > max_single_hanzi) break;
            }
        }
        cand_num = multi + single;
        delete cand_buf;
    }

    switch(currentpage)
    {
    case 1:
        if(cand_num > chinese_characters_list.length() && page_change_times < cand_num - chinese_characters_list.length())
            page_change_times++;
        break;
    case -1:
        if(page_change_times > 0) page_change_times--;
        break;
    default:
        page_change_times = 0;
        break;
    }
    if(0 == page_change_times)
        change_chinese_characters_page_list.at(0)->setEnabled(false);
    else
        change_chinese_characters_page_list.at(0)->setEnabled(true);
    if(page_change_times == cand_num - chinese_characters_list.length())
        change_chinese_characters_page_list.at(1)->setEnabled(false);
    else
        change_chinese_characters_page_list.at(1)->setEnabled(true);

    char16 *cand_buf = new char16[max_decoded_length];
    char16 *cand;
    QString cand_str;
    for (unsigned i = 0; i < cand_num; i++)
    {
        cand = im_get_candidate(i, cand_buf, max_decoded_length);
        if (cand)
        {
            cand_str = QString::fromUtf16(cand);
            if (i == 0) cand_str.remove(0, im_get_fixed_len());
        }
        else
        {
            cand_str = "";
        }
        int tmpindex = i - page_change_times;
        if(tmpindex >= 0 && tmpindex < chinese_characters_list.length())
        {
            switch(currentpage)
            {
            case 1:
                chinese_characters_list.at(tmpindex)->setText(cand_str);
                break;
            case -1:
                chinese_characters_list.at(tmpindex)->setText(cand_str);
                break;
            default:
                chinese_characters_list.at(tmpindex)->setText(cand_str);
                break;
            }
        }
    }
    delete cand_buf;
}

修改TgtsmlPlatformInputContext.cpp

#include "tgtsmlplatforminputcontext.h"
#include <QCoreApplication>
#include <QKeyEvent>
#include <QApplication>
#include <QDesktopWidget>

TgtsmlPlatformInputContext::TgtsmlPlatformInputContext()
{
    m_focusitem = nullptr;
    m_keyboard = nullptr;
}

TgtsmlPlatformInputContext::~TgtsmlPlatformInputContext()
{
    disconnect(m_keyboard, &KeyboardForm::sendKeyToFocusItem, this, &TgtsmlPlatformInputContext::sendKeyToFocusItem);
    if(m_keyboard) delete m_keyboard;
}

void TgtsmlPlatformInputContext::sendKeyToFocusItem(const QString &keytext)
{
    if(!m_focusitem)return;

    if(keytext == QString("\x7F"))     //Backspace <--
    {
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::ControlModifier));
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier));
    }
    else if(keytext == QString("\x01"))     //Backspace <--
    {
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::ShiftModifier));
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier));
    }
    else
    {
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, keytext));
        QCoreApplication::sendEvent(m_focusitem, new QKeyEvent(QEvent::KeyRelease, 0, Qt::NoModifier, keytext));
    }
}

bool TgtsmlPlatformInputContext::isValid() const
{
    return true;
}

void TgtsmlPlatformInputContext::setFocusObject(QObject *object)
{
    m_focusitem = object;
}

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));
        int height=widgetTmp->height();
        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,height);
        }
        m_keyboard->move(widgetGlobalPos);
    }
}

void TgtsmlPlatformInputContext::hideInputPanel()
{
    if(!m_keyboard){
        return;
    }
    if(!m_keyboard->isHidden()){
        m_keyboard->hide();
    }
    m_keyboard->clearChineseCache();
}

bool TgtsmlPlatformInputContext::isInputPanelVisible() const
{
    return m_keyboard->isVisible();
}

void TgtsmlPlatformInputContext::KeyPress(QKeyEvent *e)
{
    m_keyboard->KeyPress(e);
}

修改TgtsmlPlatformInputContextPlugin.cpp

#include "tgtsmlplatforminputcontextplugin.h"

TgtsmlPlatformInputContext * TgtsmlPlatformInputContextPlugin::create(const QString &key, const QStringList &paramlist)
{
    Q_UNUSED(paramlist)

    if(key.compare("tgtsml",Qt::CaseInsensitive) == 0)
    {
        return new TgtsmlPlatformInputContext;
    }
    return nullptr;
}

2 输入法插件


插件是博主tgtsml写的:Qt5输入法实现
github地址:tgtsml/QtInputMethod_GooglePinyin

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值