最近使用qt, 苦于没有找到输入法,下了几个版本后,运行也没好的。 要不没有中文,要不直接英文输入都成问题。 于是我就自己用了一些时间,写了输入法。 随着了解的深入, 发现qt输入法有两个接口。 一个是QInputContext。一个是QWSInputMethod。 这两个我的理解是QInputContext 通用些。而且高版本都用这个。 QWSMethod 就是大多应用嵌入式,适用低版本。 在之前先提示下关于中文乱码的问题, 请在创建了QApplication之后调用:
QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
两种输入的使用方法。
QInputContext:
QInputContext *im = new InputMethod();
app.setInputContext( im );
QWSInputMethod:
QWSInputMethod *im = new myInput;
QWSServer::setCurrentInputMethod( im );
im->updateHandler( QWSInputMethod::FocusIn );
im->updateHandler( QWSInputMethod::FocusOut );
关于这两个输入法的共同点就是 一般为两个部分。 一个部分是你的键盘布局。 一个部分是实现与如上两个类的。 先说说QWSInputMethod这个方法是我主要写的。 因为写在板子商用的。 Qt版本低。
派生QWSInputMethod类。
myinput.h
#ifndef MYINPUT_H #define MYINPUT_H
#include <QWSInputMethod> #include "keyboard.h"
class myInput : public QWSInputMethod { Q_OBJECT
public: myInput(); ~myInput(); void updateHandler(int type); private: void updatePosition();
private slots: void recvChar( QChar c );
private: KeyBoard *m_ky; };
#endif // MYINPUT_H
myinput.cpp
#include "myinput.h"
myInput::myInput() : QWSInputMethod() { m_ky = new KeyBoard;
connect( m_ky, SIGNAL( characterGenerated( QChar ) ), SLOT( recvChar( QChar ) ) ); }
myInput::~myInput() { delete m_ky; }
void myInput::updateHandler(int type) { switch(type) { case QWSInputMethod::FocusIn: { m_ky->show(); updatePosition(); break; } case QWSInputMethod::FocusOut: { m_ky->hide(); break; } default: break; } }
void myInput::updatePosition() { m_ky->AdjustInputPos(); }
void myInput::recvChar( QChar c ) { QPointer<QWidget> w = QApplication::focusWidget(); if (!w) return;
/* 当收到按键面板的按键输入后,分别向当前焦点Widget发送KeyPress和KeyRelease事件 */
QKeyEvent keyPress(QEvent::KeyPress, c.unicode(), Qt::NoModifier, QString(c)); QApplication::sendEvent(w, &keyPress);
if (!w) return;
QKeyEvent keyRelease(QEvent::KeyRelease, c.unicode(), Qt::NoModifier, QString(c)); QApplication::sendEvent(w, &keyRelease); }
这个类的代码主要是设置输入法的显示位置。 还有我把输入英文的处理也放在这里的。 主要是好区分。
关于Keyboard代码的。就不贴了,有点多。 Keyboard就包含了键盘布局 (是全键盘哦),处理中文信息。
还有个类就是读取中文的。
HanziManage 该类为了少写点文件放在Keyboard里面。 可以自己分开。
class HanziManage{ public: HanziManage( std::string filename); ~HanziManage();
int setHanziPage( std::string key ); int currentPageHanzi( std::vector<std::string > & v ); void pageUp(); void pageDown();
private: int readFile(std::string filename); private: std::map< std::string, std::string > m_mapData; std::multimap< int, std::string > m_mapPage; int m_page_num; int m_current_page; } ;
实现部分。
//******************************************************* // //class HanziManage ; //read hanzi from file; // //********************************************************
HanziManage::HanziManage( std::string filename ) : m_current_page( 0 ), m_page_num( 0 ) { m_mapData.clear(); m_mapPage.clear();
readFile( filename ); }
HanziManage::~HanziManage() {
}
int HanziManage::readFile(std::string name) { std::ifstream in( name.c_str() ); if(!in) { printf("Can not find %s \n", name.c_str()); return -1; } std::string line; getline( in, line, '\n' ); while(!in.eof()) { std::string strLine( line );
std::string::size_type index = 0; std::string::size_type pos = 0; if( ( index = strLine.find( ' ', pos) ) != std::string::npos ) { std::string key = strLine.substr( pos, index ); std::string val = strLine.substr( index + 1 ); m_mapData.insert( std::pair< std::string , std::string >( key, val ) ); } getline( in, line, '\n' ); }
return 0; }
int HanziManage::setHanziPage(std::string py ) { m_mapPage.clear(); m_current_page = 0; m_page_num = 0;
std::map<std::string , std::string >::const_iterator iter = m_mapData.find( py ); if( iter == m_mapData.end() ) { printf( "not find pinyin \n "); return -1; }
std::string strHanzi = iter->second; std::cout<< strHanzi.c_str() << "\n";
std::string::size_type index = 0; std::string::size_type pos = 0; int pageNum = 0; while( (index = strHanzi.find( ' ', pos ) ) != std::string::npos ) { std::string hanzi = strHanzi.substr( pos, index - pos ); m_mapPage.insert( std::pair< int, std::string >( m_page_num, hanzi ) ); ++pageNum; pos = index + 1;
if( pageNum % 6 == 0 ) { ++m_page_num ; } } if( pageNum % 6 == 0 ) --m_page_num; return 0; }
int HanziManage::currentPageHanzi( std::vector<std::string > & v ) { if( m_mapPage.empty() ) { return -1; } if( m_current_page > m_page_num ) { return -1; }
typedef std::multimap< int, std::string >::const_iterator mmiter; std::pair< mmiter, mmiter > iter = m_mapPage.equal_range( m_current_page ); mmiter it = iter.first; while( it != iter.second ) { v.push_back( it->second ); ++it; }
return v.size(); }
void HanziManage::pageDown( ) { if( m_current_page >= m_page_num ) { return ; } ++m_current_page; }
void HanziManage::pageUp( ) { if( m_current_page <= 0 ) { return ; } --m_current_page; }
该类读取中文到map中,然后输入拼音 开始查找所属拼音的汉字。在放进map里,按页存放。 我这里规定每页六个汉字。
之后currentPageHanzi 来获取当页的汉字。 而翻页这是pageUp pageDown.
基于 QWSInputMethod的输入法就介绍完了。 关于源代码下面将会发地址。 接下来介绍QInputContext的输入法了 这个Keyboard 与 HanziManage完全相同。直说 实现QInputContext的部分。
inputmethod.h
#include "keyboard.h" #include "qinputcontext.h"
class InputMethod:public QInputContext { Q_OBJECT public: InputMethod(); ~InputMethod();
bool eventFilter(QObject *obj, QEvent *event);
QString identifierName(); QString language();
void reset(); void update(); bool filterEvent( const QEvent *event ); bool isComposing() const;
public: KeyBoard *keyboard;
public: void showKeyBoard();
signals: void setImObjName(QString); private slots: void setInputText(QChar c);
};
#endif // INPUTMETHOD_H
inputmethod.cpp
#include "inputmethod.h" #include "login.h"
InputMethod::InputMethod() { keyboard = new KeyBoard; connect( keyboard, SIGNAL( characterGenerated(QChar) ), SLOT(setInputText(QChar ) ) ); }
InputMethod::~InputMethod() { delete keyboard; }
/* * Name : void eventFilter(QObject *obj, QEvent *event); * Type : QEvent * Func : judge input method event * In : QObject,QEvent * Out : bool */ bool InputMethod::eventFilter(QObject *obj, QEvent *event) { if(event->type()==QEvent::MouseButtonPress) { emit setImObjName(obj->objectName()); showKeyBoard(); return true; }
return QObject::eventFilter(obj,event); }
/* * Name : void showKeyBoard(); * Type : function * Func : show keyBoard * In : Null * Out : Null */ void InputMethod::showKeyBoard() { keyboard->move(50,120); keyboard->show(); }
void InputMethod::setInputText( QChar c ) { QPointer<QWidget> w = QApplication::focusWidget(); if (!w) return;
/* 当收到按键面板的按键输入后,分别向当前焦点Widget发送KeyPress和KeyRelease事件 */
QKeyEvent keyPress(QEvent::KeyPress, c.unicode(), Qt::NoModifier, QString(c)); QApplication::sendEvent(w, &keyPress);
if (!w) return;
QKeyEvent keyRelease(QEvent::KeyRelease, c.unicode(), Qt::NoModifier, QString(c)); QApplication::sendEvent(w, &keyRelease); }
QString InputMethod::identifierName() { return ""; } QString InputMethod::language() { return ""; }
void InputMethod::reset() { } void InputMethod::update() { }
bool InputMethod::isComposing() const { return true; }
bool InputMethod::filterEvent( const QEvent *event ) { if (event->type() == QEvent::RequestSoftwareInputPanel)
{
/* 当某个Widget请求软键盘输入时,显示软键盘 */ keyboard->show(); return true; }
else if (event->type() == QEvent::CloseSoftwareInputPanel)
{
/* 当某个Widget请求关闭软键盘输入时,关闭软键盘 */ keyboard->hide(); //这里源代码里呗注释了 调试的时候,请下载后自行删除注释。 return true; } return false;
}
大部分代码已经发出来了。 写qt的输入法赶紧比minigui的输入法好多了。 哈哈 不是贬低哈。 minigui灵活,方便,但是不易用。 qt方便,纯面向对象的。
这里再说哈,其实这界面是我下的别人改的。我不想搞界面。没有美术细胞。
这里感谢哈他。 没有他的界面我也不想搞这输入法。这界面看起来很舒服。我懒得截图了我去掉了图片。因为我现在还板子没得库看不到我就干脆去掉了。 附上这位仁兄的博客:http://blog.csdn.net/tandesir/article/details/7283158 。
别搞错了这个是博客 下载地址在最后
源代码下载地址。 http://download.csdn.net/detail/asb2010/5444121 字库文件是.db文件 该文件格式是ASCII。如果你发现乱码请看该文件格式是否正确。