使用Qt5 QWidget实现键盘输入法
一、前言
以前写的一个输入法,本来完善的已经很好了,但最近工作需要,再次把输入法拿出来捣鼓了一番,网上也有很多类似的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.youkuaiyun.com/download/taoshiwu/20028342
竖屏输入法Demo:https://download.youkuaiyun.com/download/taoshiwu/20028363
七、结语
1、能不重复造轮子就不重复造轮子。
2、感谢QT君。
3、感谢优快云上的各位大神。