2021-07-04

Linux Qt5中文输入法_软键盘

一、前言

以前写的一个输入法,本来完善的已经很好了,但最近工作需要,再次把输入法拿出来捣鼓了一番,网上也有很多类似的Demo,但是比较杂,其他大佬做的输入法不是代码了多且难懂,就是界面做的超级简单不实用,之前做输入法也能用,觉得还是不够美观,后面也陆陆续续优化了界面和BUG。

二、功能特点

1、纯QWidget编写,,使用QT5版本编写,Qt4未测过,目标运行平使用windows、嵌入式linux测试过都OK。
2、输入法调用方便,移植只需把keyboard的h文件,c文件,ui文件和qrc资源文件包含稍作调整即可。
3、代码量的话只有六百行左右,代码结构清晰,有详细注释,非常容易阅读和理解。
4、键盘界面清晰简洁,UI美观,横屏类似于QT官方键盘风格,竖屏类似于搜手机键盘风格。
5、顶部滑动选词,插入文本功能,连续删除文本功能。
6、可自定义增减词组,直接打开txt字库文件写入自定义词组即可。
7、支持中文、英文大小写、数字、特殊符号输入,支持单拼、全拼、模糊拼音输入。

三、效果图

1、使用效果图
在这里插入图片描述

2、界面截图
横屏Demo
在这里插入图片描述
竖屏Demo
在这里插入图片描述

四、模块讲解

1、标题中文候选栏
中文输入候选栏MyListWidget使用QListWidget和样式表实现:
setText:输入对应拼音字母,即会加载符合的拼音中文。
addOneItem:添加候选词。
loadData和loadData2:加载本地词组。
pressedChanged:信号为当按键按下,传递对应的中文。
onItemClicked:槽函数为传递中文。
//用于存放候选词

class MyListWidget : public QListWidget {
    Q_OBJECT
public:
    MyListWidget(QWidget *parent = nullptr);
    void setText(const QString &text);
    void addOneItem(const QString &text);
    void loadData();
    void loadData2();

signals:
    void pressedChanged(const int &code, const QString &text);

private slots:
    void onItemClicked(QListWidgetItem *item);

private:
    QMap<QString, QList<QPair<QString, QString>> > m_data;
};

2、设置QListWidget
配置QListWidget外观以及信号与槽的关联。

MyListWidget::MyListWidget(QWidget *parent) :
    QListWidget(parent)
{
    loadData();
    loadData2();
    setFocusPolicy(Qt::NoFocus);
    setViewMode(QListView::ListMode);   //设置为列表显示模式
    setFlow(QListView::LeftToRight);    //从左往右排列
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);   //屏蔽水平滑动条
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);     //屏蔽垂直滑动条
    setHorizontalScrollMode(QListWidget::ScrollPerPixel);   //设置为像素滚动
    QScroller::grabGesture(this, QScroller::LeftMouseButtonGesture);    //设置鼠标左键拖动
    //设置样式
    setStyleSheet(R"(
                    QListWidget { outline: none; border:1px solid #00000000; background-color:rgb(30,27,24); color:rgb(128,195,24); }
                    QListWidget::Item { width: 50px; height: 50px; }
                    QListWidget::Item:hover { background: #4395ff; color: white; }
                    QListWidget::item:selected { background: #4395ff; color: black; }
                    QListWidget::item:selected:!active { background: #00000000; color: red; }
                  )");

    connect(this, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(onItemClicked(QListWidgetItem *)));
    setText("");
}

3、事件过滤函数
总事件过滤器功能是获取所有QPushButton文本然后再根据这些文本做相应的处理。
代码中PushButton_Filtration函数功能是过滤功能键,如大小写切换,符号切换,数字切换,删除,回车等。
keyInput函数功能是处理字符文本,比如是输出英文字符还是中文数字等。

//总事件过滤器
bool Keyboard::eventFilter(QObject *obj, QEvent *_event)
{
    //键盘事件处理
    //qDebug()<<"-----event3:"<<_event;
    if(_event->type() == QEvent::MouseButtonPress)   //点击按键
    {
        if(PushButton_Filtration(obj->objectName()))
            return QWidget::eventFilter(obj,_event);
        QString text = static_cast<QPushButton *>(obj)->text();
        if(obj->objectName()=="pushButton_Pinyin_Space" || obj->objectName()=="pushButton_Num_Space")
        {
            text = " ";
            keyInput(text);  //传空格键
            return QWidget::eventFilter(obj,_event);
        }
        keyInput(text);
    }
    return QWidget::eventFilter(obj,_event);
}

4、词组显示设置
这里也比较重要的,下面代码是设置候选栏中词组文本大小,显示长度以及显示间距的代码。
如果出现拼音或词组过长显示不完整,调节代码中小数即可。

void MyListWidget::addOneItem(const QString &text)
{
    QListWidgetItem *item = new QListWidgetItem(text, this);
    QFont font;
    font.setPointSize(13);
    font.setBold(true);
    font.setWeight(50);
    item->setFont(font);

    item->setTextAlignment(Qt::AlignCenter);      //设置文字居中
    bool isChinese = QRegExp("^[\u4E00-\u9FA5]+").indexIn(text.left(1)) != -1;  //检测Item项的文字查是否为中文

    int width = font.pointSize();       //width:18
    if (isChinese)
        width += text.count()*font.pointSize()*2.4;
    else
        width += text.count()*18;
    item->setSizeHint(QSize(width, 50));
    addItem(item);
}

五、核心代码

这里是横屏版的核心代码,竖屏版的也基本一样。

#include "keyboard.h"
#include "ui_keyboard.h"
#include <QScroller>
#include <QRegExp>

Keyboard::Keyboard(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Keyboard)
{
    ui->setupUi(this);

    LanguageItem = 0;   //默认为中文输入状态
    NumKeyboardFlag = false;
    ui->lineEdit_Input->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    ui->lineEdit_Input->setStyleSheet(R"(QLineEdit{border-style: none; padding: 3px; border-radius: 5px; border: 1px solid #dce5ec; font-size: 30px;})");

    ChineseWidget = new MyListWidget;
    ChineseWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    ui->horizontalLayout_Chinese->addWidget(ChineseWidget);

    //连接进入符号键盘按钮
    connect(ui->pushButton_Pinyin_Symbol,SIGNAL(clicked()),this,SLOT(Slot_Enter_into_Symbol()));
    //连接进入数字键盘按钮
    connect(ui->pushButton_Pinyin_Num,SIGNAL(clicked()),this,SLOT(Slot_Enter_into_Num()));
    //删除键点击信号
    connect(ui->pushButton_Pinyin_Backspace,SIGNAL(pressed()),this,SLOT(Slot_Backspace_pressed_State()));
    connect(ui->pushButton_Num_Backspace,SIGNAL(pressed()),this,SLOT(Slot_Backspace_pressed_State()));
    //删除键松开信号
    connect(ui->pushButton_Pinyin_Backspace,SIGNAL(released()),this,SLOT(Slot_Backspace_released_State()));
    connect(ui->pushButton_Num_Backspace,SIGNAL(released()),this,SLOT(Slot_Backspace_released_State()));
    TimerDel = new QTimer;
    connect(TimerDel,SIGNAL(timeout()),this,SLOT(Slot_Delete_Char()));      //用于连续删除文本
    TimerDel->stop();
    //连接Enter回车按钮
    connect(ui->pushButton_Pinyin_Enter,SIGNAL(clicked()),this,SLOT(Slot_Back_Enter_clicked()));
    connect(ui->pushButton_Num_Enter,SIGNAL(clicked()),this,SLOT(Slot_Back_Enter_clicked()));

    QList<QPushButton *> list_PushButton = findChildren<QPushButton *>();
    foreach(QPushButton *p,list_PushButton)
        p->installEventFilter(this);    //总事件过滤器关联按钮

    connect(ChineseWidget,SIGNAL(pressedChanged(const int &,const QString &)),this,SLOT(onKeyPressed(const int &, const QString &)));    //发送选择的文本到LineEdit
    connect(ChineseWidget,SIGNAL(pressedChanged(const int &,const QString &)),this,SLOT(clearBufferText()));  //发送完后清空候选栏
}

Keyboard::~Keyboard()
{
    delete ui;
    delete ChineseWidget;
}

void Keyboard::showEvent(QShowEvent *)
{
    ui->lineEdit_Input->setFocus();
    ui->stackedWidget_Key->setCurrentIndex(0);  //进入拼音键盘页面
    //设置键盘颜色
    QList<QPushButton *> list_PushButton = findChildren<QPushButton *>();
    foreach(QPushButton *p,list_PushButton)
        p->setStyleSheet("QPushButton{background-color:rgb(56,53,51);} QPushButton{color:rgb(255,255,255);} QPushButton:hover{background-color:blue;} QPushButton:pressed{background-color:gray}");
    ui->pushButton_Pinyin_Cap->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Pinyin_Backspace->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Pinyin_Symbol->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Pinyin_Language->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Pinyin_Num->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Pinyin_Enter->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Symbol_Back->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Symbol_SBC->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Num_Backspace->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Num_More->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Num_Space->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Num_Back->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
    ui->pushButton_Num_Enter->setStyleSheet("background-color:rgb(30,27,24); color:rgb(255,255,255);");
}

//总事件过滤器
bool Keyboard::eventFilter(QObject *obj, QEvent *_event)
{
    //键盘事件处理
    //qDebug()<<"-----event3:"<<_event;
    if(_event->type() == QEvent::MouseButtonPress)   //点击按键
    {
        if(PushButton_Filtration(obj->objectName()))
            return QWidget::eventFilter(obj,_event);
        QString text = static_cast<QPushButton *>(obj)->text();
        if(obj->objectName()=="pushButton_Pinyin_Space" || obj->objectName()=="pushButton_Num_Space")
        {
            text = " ";
            keyInput(text);  //传空格键
            return QWidget::eventFilter(obj,_event);
        }
        keyInput(text);
    }
    return QWidget::eventFilter(obj,_event);
}

//过滤功能按钮
bool Keyboard::PushButton_Filtration(QString ObjectName)
{
    if(ObjectName=="pushButton_Pinyin_Cap" || ObjectName=="pushButton_Pinyin_Backspace" || ObjectName=="pushButton_Pinyin_Symbol" || \
       ObjectName=="pushButton_Pinyin_Language" || ObjectName=="pushButton_Pinyin_Num" || ObjectName=="pushButton_Pinyin_Enter")
        return true;
    else if(ObjectName=="pushButton_Symbol_Back" || ObjectName=="pushButton_Symbol_SBC" || ObjectName=="pushButton_Num_Backspace" || \
            ObjectName=="pushButton_Num_More" || ObjectName=="pushButton_Num_Back" || ObjectName=="pushButton_Num_Enter")
        return true;
    else
        return false;
}

void Keyboard::PushButton_Language_Text(QString Str)
{
    ui->pushButton_Pinyin_Language->setText(Str);
}

void Keyboard::on_button_clicked(QString txt)
{
    qDebug()<<"-----txt1:"<<txt;
}

/****************************** 拼音键盘 **********************************/
void Keyboard::on_pushButton_Pinyin_Language_clicked()
{
    if(ui->pushButton_Pinyin_Language->text() == "中文")
    {
        LanguageItem = 1;
        ui->pushButton_Pinyin_Language->setText("En");
        ui->pushButton_Pinyin_Comma->setText(",");
        ui->pushButton_Pinyin_Period->setText(".");
    }
    else if(ui->pushButton_Pinyin_Language->text() == "En")
    {
        LanguageItem = 0;
        ui->pushButton_Pinyin_Language->setText("中文");
        ui->pushButton_Pinyin_Comma->setText(",");
        ui->pushButton_Pinyin_Period->setText("。");
    }
}

//切换大小写
void Keyboard::on_pushButton_Pinyin_Cap_clicked()
{
    if(Cap_Aa_Flag)
    {
        Cap_Aa_Flag = false;
        ui->pushButton_Pinyin_Q->setText("Q");
        ui->pushButton_Pinyin_W->setText("W");
        ui->pushButton_Pinyin_E->setText("E");
        ui->pushButton_Pinyin_R->setText("R");
        ui->pushButton_Pinyin_T->setText("T");
        ui->pushButton_Pinyin_Y->setText("Y");
        ui->pushButton_Pinyin_U->setText("U");
        ui->pushButton_Pinyin_I->setText("I");
        ui->pushButton_Pinyin_O->setText("O");
        ui->pushButton_Pinyin_P->setText("P");
        ui->pushButton_Pinyin_A->setText("A");
        ui->pushButton_Pinyin_S->setText("S");
        ui->pushButton_Pinyin_D->setText("D");
        ui->pushButton_Pinyin_F->setText("F");
        ui->pushButton_Pinyin_G->setText("G");
        ui->pushButton_Pinyin_H->setText("H");
        ui->pushButton_Pinyin_J->setText("J");
        ui->pushButton_Pinyin_K->setText("K");
        ui->pushButton_Pinyin_L->setText("L");
        ui->pushButton_Pinyin_Z->setText("Z");
        ui->pushButton_Pinyin_X->setText("X");
        ui->pushButton_Pinyin_C->setText("C");
        ui->pushButton_Pinyin_V->setText("V");
        ui->pushButton_Pinyin_B->setText("B");
        ui->pushButton_Pinyin_N->setText("N");
        ui->pushButton_Pinyin_M->setText("M");
    }
    else
    {
        Cap_Aa_Flag = true;
        ui->pushButton_Pinyin_Q->setText("q");
        ui->pushButton_Pinyin_W->setText("w");
        ui->pushButton_Pinyin_E->setText("e");
        ui->pushButton_Pinyin_R->setText("r");
        ui->pushButton_Pinyin_T->setText("t");
        ui->pushButton_Pinyin_Y->setText("y");
        ui->pushButton_Pinyin_U->setText("u");
        ui->pushButton_Pinyin_I->setText("i");
        ui->pushButton_Pinyin_O->setText("o");
        ui->pushButton_Pinyin_P->setText("p");
        ui->pushButton_Pinyin_A->setText("a");
        ui->pushButton_Pinyin_S->setText("s");
        ui->pushButton_Pinyin_D->setText("d");
        ui->pushButton_Pinyin_F->setText("f");
        ui->pushButton_Pinyin_G->setText("g");
        ui->pushButton_Pinyin_H->setText("h");
        ui->pushButton_Pinyin_J->setText("j");
        ui->pushButton_Pinyin_K->setText("k");
        ui->pushButton_Pinyin_L->setText("l");
        ui->pushButton_Pinyin_Z->setText("z");
        ui->pushButton_Pinyin_X->setText("x");
        ui->pushButton_Pinyin_C->setText("c");
        ui->pushButton_Pinyin_V->setText("v");
        ui->pushButton_Pinyin_B->setText("b");
        ui->pushButton_Pinyin_N->setText("n");
        ui->pushButton_Pinyin_M->setText("m");
    }
}

/****************************** 标点键盘 **********************************/
//全角、半角
void Keyboard::on_pushButton_Symbol_SBC_clicked()
{
    if(ui->pushButton_Symbol_SBC->text() == "半角")
    {
        ui->pushButton_Symbol_SBC->setText("全角");
        ui->pushButton_Symbol_1->setText(",");
        ui->pushButton_Symbol_2->setText("。");
        ui->pushButton_Symbol_3->setText("!");
        ui->pushButton_Symbol_4->setText("?");
        ui->pushButton_Symbol_5->setText(":");
        ui->pushButton_Symbol_6->setText(";");
        ui->pushButton_Symbol_7->setText("‘’");
        ui->pushButton_Symbol_8->setText("“”");
        ui->pushButton_Symbol_9->setText("【");
        ui->pushButton_Symbol_10->setText("】");
        ui->pushButton_Symbol_13->setText("《");
        ui->pushButton_Symbol_14->setText("》");
        ui->pushButton_Symbol_15->setText("\\");
        ui->pushButton_Symbol_20->setText("¥");
        ui->pushButton_Symbol_22->setText("……");
        ui->pushButton_Symbol_24->setText("×");
        ui->pushButton_Symbol_25->setText("(");
        ui->pushButton_Symbol_26->setText(")");
        ui->pushButton_Symbol_27->setText("--");

    }
    else if(ui->pushButton_Symbol_SBC->text() == "全角")
    {
        ui->pushButton_Symbol_SBC->setText("半角");
        ui->pushButton_Symbol_1->setText(",");
        ui->pushButton_Symbol_2->setText(".");
        ui->pushButton_Symbol_3->setText("!");
        ui->pushButton_Symbol_4->setText("?");
        ui->pushButton_Symbol_5->setText(":");
        ui->pushButton_Symbol_6->setText(";");
        ui->pushButton_Symbol_7->setText("'");
        ui->pushButton_Symbol_8->setText("\"");
        ui->pushButton_Symbol_9->setText("[");
        ui->pushButton_Symbol_10->setText("]");
        ui->pushButton_Symbol_13->setText("<");
        ui->pushButton_Symbol_14->setText(">");
        ui->pushButton_Symbol_15->setText("/");
        ui->pushButton_Symbol_20->setText("$");
        ui->pushButton_Symbol_22->setText("^");
        ui->pushButton_Symbol_24->setText("*");
        ui->pushButton_Symbol_25->setText("(");
        ui->pushButton_Symbol_26->setText(")");
        ui->pushButton_Symbol_27->setText("_");
    }
}

//标点键盘返回
void Keyboard::on_pushButton_Symbol_Back_clicked()
{
    if(NumKeyboardFlag)
    {
        ui->stackedWidget_Key->setCurrentIndex(1);  //进入数字键盘页面
        return;
    }
    ui->stackedWidget_Key->setCurrentIndex(PrevIndexWidget);  //返回上一层页面
}


/****************************** 数字键盘 **********************************/
void Keyboard::on_pushButton_Num_More_clicked()
{
    ui->stackedWidget_Key->setCurrentIndex(2);  //进入标点符号页面
}

//数字键盘返回
void Keyboard::on_pushButton_Num_Back_clicked()
{
    NumKeyboardFlag = false;    //退出数字键盘标志
    ui->stackedWidget_Key->setCurrentIndex(PrevIndexWidget);  //返回上一层页面
}

//公共槽函数(进入符号键盘)
void Keyboard::Slot_Enter_into_Symbol()
{
    PrevIndexWidget = ui->stackedWidget_Key->currentIndex(); //记录当前页面
    ui->stackedWidget_Key->setCurrentIndex(2);  //进入标点符号页面
}

//公共槽函数(进入数字键盘)
void Keyboard::Slot_Enter_into_Num()
{
    NumKeyboardFlag = true;     //进入数字键盘标志
    PrevIndexWidget = ui->stackedWidget_Key->currentIndex(); //记录当前页面
    ui->stackedWidget_Key->setCurrentIndex(1);  //进入数字键盘页面
}

void Keyboard::Slot_Backspace_pressed_State()
{
    //qDebug()<<"-----Delete";
    if(ChineseWidget->item(0)->text() != "")
    {
        TextBuffer.chop(1);
        ChineseWidget->setText(TextBuffer);
    }
    else if(ui->lineEdit_Input->hasFocus())
        ui->lineEdit_Input->backspace();
    DeleteCharCount = 0;
    TimerDel->start(200);
}

void Keyboard::Slot_Backspace_released_State()
{
    TimerDel->stop();
}

void Keyboard::Slot_Delete_Char()
{
    DeleteCharCount++;
    if(DeleteCharCount == 5)
        TimerDel->start(100);
    if(ChineseWidget->item(0)->text() != "")
    {
        TextBuffer.chop(1);
        ChineseWidget->setText(TextBuffer);
    }
    else if(ui->lineEdit_Input->hasFocus())
        ui->lineEdit_Input->backspace();
}

//公共槽函数(回车按钮)
void Keyboard::Slot_Back_Enter_clicked()
{
    updateCand();
    sendTextSlot();  //
    this->parentWidget()->show();
    this->hide();
}

/************************************************************************/
//更新候选词
void Keyboard::updateCand()
{
    ChineseWidget->setText("");
}

//拼音获取
void Keyboard::keyInput(QString &s)
{
    if(ui->stackedWidget_Key->currentIndex()==0)    //键盘界面pushButton text获取
    {
        if(LanguageItem == 0)       //输入状态为中文
        {
            if (s[0] >= 'a' && s[0] <= 'z')
            {
                TextBuffer.append(s);
                ChineseWidget->setText(TextBuffer);
            }
            else if(s[0] >= 'A' && s[0] <= 'Z')
                ui->lineEdit_Input->insert(s);
            else if(s=="," || s=="。" || s==" ")   //中文状态下,键盘的两个符号和空格不能过滤
                ui->lineEdit_Input->insert(s);
        }
        else if(LanguageItem == 1)  //输入状态为英文
            ui->lineEdit_Input->insert(s);
    }
    else    //为字符,数字界面
    {
        if(s == "&&")
            ui->lineEdit_Input->insert("&");
        else
            ui->lineEdit_Input->insert(s);
    }
}

void Keyboard::onKeyPressed(int key, QString value)
{
    qDebug() << "key: " << key << "Value: " << value;
    ui->lineEdit_Input->insert(value);
}

//清空拼音
void Keyboard::clearBufferText()
{
    TextBuffer.clear();
    ChineseWidget->setText("");
}


/*------------------------------------------------ QLineEdit -----------------------------------------------------*/
//发送信号
void Keyboard::sendTextSlot()
{
    QString text = ui->lineEdit_Input->text();
    qDebug()<<"sendTextSlot,sendtext:"<<text;
    emit sendText(text);
}

void Keyboard::setLineEditText(QString text)
{
    ui->lineEdit_Input->setText(text);
}

void Keyboard::clearText()
{
    ui->lineEdit_Input->clear();
}

QString Keyboard::getText()
{
    return ui->lineEdit_Input->text();
}


/*------------------------------------------------ QListWidget -----------------------------------------------------*/
MyListWidget::MyListWidget(QWidget *parent) :
    QListWidget(parent)
{
    loadData();
    loadData2();
    setFocusPolicy(Qt::NoFocus);
    setViewMode(QListView::ListMode);   //设置为列表显示模式
    setFlow(QListView::LeftToRight);    //从左往右排列
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);   //屏蔽水平滑动条
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);     //屏蔽垂直滑动条
    setHorizontalScrollMode(QListWidget::ScrollPerPixel);   //设置为像素滚动
    QScroller::grabGesture(this, QScroller::LeftMouseButtonGesture);    //设置鼠标左键拖动
    //设置样式
    setStyleSheet(R"(
                    QListWidget { outline: none; border:1px solid #00000000; background-color:rgb(30,27,24); color:rgb(128,195,24); }
                    QListWidget::Item { width: 50px; height: 50px; }
                    QListWidget::Item:hover { background: #4395ff; color: white; }
                    QListWidget::item:selected { background: #4395ff; color: black; }
                    QListWidget::item:selected:!active { background: #00000000; color: red; }
                  )");

    connect(this, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(onItemClicked(QListWidgetItem *)));
    setText("");
}

//2020.7.29  tao
void MyListWidget::setText(const QString &text)
{
    int cnt=0;
    for (int i = 0; i < count(); i++) {
        QListWidgetItem *item = takeItem(i);
        delete item;
        item = NULL;
    }

    clear();

    addOneItem(text);
    //qDebug()<<"--text:"<<text;
    if (! m_data.contains(text.left(1))) {
        return;
    }
    if(text.size()==1)  //打第一个字母情况下查找本地词库
    {
        /* 通过获取首字母索引词库内容,用于加快匹配词(组)。 */
        const QList<QPair<QString, QString>> &tmp = m_data[text.left(1)];
        for(const QPair<QString, QString> &each : tmp){
            if (each.first.left(text.count()) != text)  //模糊匹配
                continue;
            addOneItem(each.second);    //添加到候选栏
            cnt++;
            if(cnt>1000) //这里加限制,不然全部遍历词库需要时间,1000是根据最多汉字的字母s而定(s开头简体字有940个)
                break;
        }
    }
    else    //组合或全拼情况下的查找本地词库
    {
        /* 通过获取首字母索引词库内容,用于加快匹配词(组)。 */
        const QList<QPair<QString, QString>> &tmp = m_data[text.left(1)];
        for(const QPair<QString, QString> &each : tmp){
            if (each.first.left(text.count()) != text)  //模糊匹配
                continue;
            addOneItem(each.second);    //添加到候选栏
        }
    }
}

void MyListWidget::onItemClicked(QListWidgetItem *item)
{
    emit pressedChanged(-1, item->text());
    setText("");
}

void MyListWidget::addOneItem(const QString &text)
{
    QListWidgetItem *item = new QListWidgetItem(text, this);
    QFont font;
    font.setPointSize(18);
    font.setBold(true);
    font.setWeight(50);
    item->setFont(font);

    item->setTextAlignment(Qt::AlignCenter);      //设置文字居中
    bool isChinese = QRegExp("^[\u4E00-\u9FA5]+").indexIn(text.left(1)) != -1;  //检测Item项的文字查是否为中文

    int width = font.pointSize();       //width:18
    if (isChinese)
        width += text.count()*font.pointSize()*1.5;
    else{
        width += text.count()*14;
        //qDebug()<<"--width:"<<width<<"  count:"<<text.count();
    }

    item->setSizeHint(QSize(width, 50));
    addItem(item);
}

void MyListWidget::loadData()
{
    QFile pinyin(":/TextLib/pinyin.txt");
    if (! pinyin.open(QIODevice::ReadOnly)) {
        qDebug() << "Open pinyin file failed!";
        return;
    }

    while (! pinyin.atEnd()) {
        QString buf = QString::fromUtf8(pinyin.readLine()).trimmed();
        QRegExp regExp("^[\u4E00-\u9FA5]+");

        int index = regExp.indexIn(buf);
        if (index == -1)
            continue;

        QString first = buf.right(buf.size() - regExp.matchedLength());
        QString second = buf.mid(index, regExp.matchedLength());

        QList<QPair<QString, QString>> &tmp = m_data[first.left(1)];
        tmp.append(qMakePair(first, second));
    }
}

void MyListWidget::loadData2()
{
    /* 加载词组字库内容 */
    QFile pinyin(":/TextLib/pinyin_phrase.txt");
    if (! pinyin.open(QIODevice::ReadOnly)) {
        qDebug() << "Open pinyin file failed!";
        return;
    }

    /* 按行读取内容 */
    while (! pinyin.atEnd()) {
        QString buf = QString::fromUtf8(pinyin.readLine()).trimmed();
        if (buf.isEmpty())
            continue;

        /* 去除#号后的注释内容 */
        if (buf.left(1) == "#")
            continue;

        /* 正则匹配词组内容并通过组捕获获取'词组'和'拼音' */
        QRegExp regExp("(\\S+): ([\\S ]+)");
        int pos = 0;
        while ((pos = regExp.indexIn(buf, pos)) != -1) {
            pos += regExp.matchedLength();
            QString second = regExp.cap(1);  /* 词组 */
            QString first = regExp.cap(2); /* 拼音 */

            QStringList strList = first.split(" ");
            QString abb;
            for (int i = 0; i < strList.count(); i++) {
                /* 获得拼音词组的首字母(用于缩写匹配) */
                abb += strList.at(i).left(1);
            }
            QList<QPair<QString, QString>> &tmp = m_data[first.left(1)];
            /* 将'拼音(缩写)'和'词组'写入匹配容器 */
            tmp.append(qMakePair(abb, second));
            /* 将'拼音(全拼)'和'词组'写入匹配容器 */
            tmp.append(qMakePair(first.remove(" "), second));
        }
    }
}

六、输入法参考例程

横屏输入法Demo:https://download.csdn.net/download/taoshiwu/20028342
竖屏输入法Demo:https://download.csdn.net/download/taoshiwu/20028363

七、结语

1、能不重复造轮子就不重复造轮子。
2、感谢QT君。
3、感谢CSDN上的各位大神。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

taoshiwu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值