英文输入法界面效果图
中文输入法界面效果图
1 界面布局
关键:留意管理器QGridLayout类的使用!
---主界面的布局
GeoImDialog::GeoImDialog(QWidget *parent, const char *name, int flags) :
QWidget(parent, name, flags) {
。。。
__parentLayout = new QGridLayout(this, 1, 1); //整个输入界面的主布局管理器
__initEnglishShiftLayout(); //初始化英语输入法点击shift后的面板
__initChineseLayout(); //初始化中文输入法的面板
__initEnglishLayout(); //初始化英文输入法的面板
__parentLayout->addWidget(__englishToShiftPanel, 0, 0); //这里很关键,把三个面板放在同一个格子内
__parentLayout->addWidget(__chinesePanel, 0, 0); //通过QWidget的show和hide方法来实现显示不同
__parentLayout->addWidget(__englishPanel, 0, 0); //的输入法
。。。
}
-----中文输入面板的制作
__initChineseLayout() {
__chinesePanel = new QWidget(this);
__chineseInputLayOut=new QGridLayout(__chinesePanel, 6, 11);//设置6行11列的网格布局管理器
__chinesePanel->setFixedSize(__inputWidth, __inputHeight);
__chineseInputLayOut->setSpacing(-1);
__chinesePanel->hide(); //因为一开始默认显示英文输入法,所以中文
//输入法面板隐藏
..............
__chineseInputLayOut->addWidget(cbtnPageLeft, 0, 0); //在第一行第一列插入往左翻页按钮
__chineseInputLayOut->addMultiCellWidget(cbtnBackspace, 1, 1, 9, 10); //在第二行第10,第11列,插入退格键,退格键占2个格子
//效果见图
...............
connect(cbtnPageLeft, SIGNAL(clicked()), this, SLOT(pageLeft())); //信号和槽的连接
connect(cbtnBackspace, SIGNAL(clicked()), this, SLOT(pinyinBackspace()));
..................
}
其他面板制作方法类似
2 添加样式
关键:留意QPalette类的使用!
这是关于QPalette的简介:
A palette consists of three color groups: a active, a disabled and an inactive color group. All widgets contain a palette, and all the widgets in Qt use their palette to draw themselves. This makes the user interface consistent and easily configurable.
If you make a new widget you are strongly advised to use the colors in the palette rather than hard-coding specific colors.
QPalette可以通过详细配置达到精确控制组件各种状态下显示效果
大概代码样式如下
QPalette pal;
QColorGroup cg;
cg.setColor(QColorGroup::Foreground, black);
cg.setColor(QColorGroup::Button, QColor( 255, 204, 102));
cg.setColor(QColorGroup::Light, white);
cg.setColor(QColorGroup::Midlight, QColor( 246, 246, 239));
cg.setColor(QColorGroup::Dark, QColor( 119, 119, 112));
cg.setColor(QColorGroup::Mid, QColor( 158, 158, 149));
cg.setColor(QColorGroup::Text, black);
cg.setColor(QColorGroup::BrightText, white);
cg.setColor(QColorGroup::ButtonText, black);
cg.setColor(QColorGroup::Base, white);
cg.setColor(QColorGroup::Background, QColor( 200, 215, 227));
cg.setColor(QColorGroup::Shadow, black);
cg.setColor(QColorGroup::Highlight, QColor( 0, 0, 128));
cg.setColor(QColorGroup::HighlightedText, white);
pal.setActive(cg);
cg.setColor(QColorGroup::Foreground, black);
cg.setColor(QColorGroup::Button, QColor( 255, 204, 102));
cg.setColor(QColorGroup::Light, white);
cg.setColor(QColorGroup::Midlight, white);
cg.setColor(QColorGroup::Dark, QColor( 119, 119, 112));
cg.setColor(QColorGroup::Mid, QColor( 158, 158, 149));
cg.setColor(QColorGroup::Text, black);
cg.setColor(QColorGroup::BrightText, white);
cg.setColor(QColorGroup::ButtonText, black);
cg.setColor(QColorGroup::Base, white);
cg.setColor(QColorGroup::Background, QColor( 200, 215, 227));
cg.setColor(QColorGroup::Shadow, black);
cg.setColor(QColorGroup::Highlight, QColor( 0, 0, 128));
cg.setColor(QColorGroup::HighlightedText, white);
pal.setInactive(cg);
cg.setColor(QColorGroup::Foreground, QColor( 128, 128, 128));
cg.setColor(QColorGroup::Button, QColor( 255, 204, 102));
cg.setColor(QColorGroup::Light, white);
cg.setColor(QColorGroup::Midlight, white);
cg.setColor(QColorGroup::Dark, QColor( 119, 119, 112));
cg.setColor(QColorGroup::Mid, QColor( 158, 158, 149));
cg.setColor(QColorGroup::Text, black);
cg.setColor(QColorGroup::BrightText, white);
cg.setColor(QColorGroup::ButtonText, QColor( 128, 128, 128));
cg.setColor(QColorGroup::Base, white);
cg.setColor(QColorGroup::Background, QColor( 200, 215, 227));
cg.setColor(QColorGroup::Shadow, black);
cg.setColor(QColorGroup::Highlight, QColor( 0, 0, 128));
cg.setColor(QColorGroup::HighlightedText, white);
pal.setDisabled(cg);
组件(QWidget)->setPalette(pal);
在这个输入法的制作中,为了省却麻烦,本身输入法不需要太复杂的样式,我们默认使用几个全局的系统定义好的样式:
namespace GeoInput {
static QPalette phusei(QColor(160, 160, 160));
static QPalette pwhite(QColor(255,255,255));
static QPalette pyellow(QColor(255,128,0));
static QPalette pblue(QColor (200, 200, 255));
}
把样式表放到单独的命名空间GeoInput内是为了防止污染全局空间域,在这个命名空间内还可以放置其他信息,比如输入法的
字体,一些输入法使用工具函数等。
然后在程序这样使用
........
cbtnPageLeft->setPalette(GeoInput::phusei); //不会些灰色的英文,只好用拼音huise,哈哈!
cbtnBackspace->setPalette(GeoInput::phusei);
.........
整个界面大致已经完成
3 中文的显示
字符编码问题是个复杂的问题,这里只简单说下能够显示汉字的最简单的步骤。
要让一个汉字显示: 我想大概有2个条件吧,一个是编码要正确,另外一个必须要有能显示这个正确编码的字符的字体存在
比如我现在linux的Eclipse3.2下工作,在程序里默认的代码编辑器的编码是UTF-8
我在这个编辑器里写下的汉字"中文输入法"5个字就是UTF-8编码的
但是QTopia平台使用的是unicode编码所以得转换下编码
QString GeoInput::trUTF8(const char* str) {
static QTextCodec *codec=QTextCodec::codecForName("UTF8");
return codec->toUnicode(str);
}
cbtnChangeInput = new QPushButton(trUTF8("中文输入法"),__chinesePanel);"
这样在QTopia下面才能正确显示按钮上的5个字(中文字体也得存在$(QPEDIR)/lib/fonts目录下,不然显示方块:))
4 汉字编码的加载
这个就比较的麻烦了,这里用的是老大写的一个类。
大概步骤如下:
--1 读取拼音表(用vector按pinyin保存)
a,阿,33237,啊,26566,呵,2000,腌,185,吖,104,嗄,60,锕,7,錒,0
ai,爱,60751,埃,5192,艾,4290,哀,4070,挨,3099,唉,2811,哎,2473,碍,2438,矮,1684,癌,576,暧,507,愛,447,嗳,444,蔼,429,捱,374,隘,242,霭,228,锿,201,皑,150,毐,122,诶,52,礙,19,嫒,11,欸,10,噯,10,曖,9,靄,3,瑷,3,騃,2,藹,2,叆,2,瞹,1,譪,1,鱫,1,娭,0,銰,0,鎄,0,㱯,0,䠹,0,䶣,0,凒,0,厓,0,呆,0,啀,0,嘊,0,娾,0,嵦,0,敱,0,敳,0,皚,0,㑸,0,㗨,0,㢊,0,䑂,0,䨠,0,佁,0,昹,0,躷,0,馤,0,㕌,0,㗒,0,㘷,0,㝶,0,㤅,0,㿄,0,䀳,0,䅬,0,䔽,0,䝽,0,䬵,0,伌,0,僾,0,呝,0,嗌,0,堨,0,塧,0,嬡,0,懓,0,懝,0,濭,0,璦,0,皧,0,砹,0,硋,0,薆,0,賹,0,鑀,0,靉,0,鴱,0
an,安,57385,案,23506。。。。。。。。。。。。
--2 读取词语表 (就是拼音输入一后自动跳出个,篇,页,常见搭配词组)
一,个,篇,页,种,样,次,些,下,点,切
丁,香,点,一,尼,零,当,基,亥,玲,忧
七,十,八,年,月,个,日,百,七,分,千
万,人,元,岁,一,年,里,分,万,物,吨
丈,夫,人,母,量
三,个,十,年,四,天,人,次,峡,分,百
上,的,去,面,海,来,帝,下,午,班,说
下,来,去,的,了,面,午,子,文,头,车
不,是,能,知,会,过,可,要,同,到,得
与,我,他,其,此,你,她,国,之,否,会
丐,帮,养
丑,陋,闻,恶,的,事,态,角,化,女,行
专,家,业,门,心,注,
--3 然后提供接口给刚才设计的UI
std::vector<QString> *getMatchChars(const char* pinyin);
std::vector<QString> *getPhraseList(QString c);
输入ling后能返回调用接口std::vector<QString> *getMatchChars(const char* pinyin)
返回包含 岭 陵 拎 。。。。的std::vector<QString>就行了:)
5 既然汉字也有了,界面也有了,现在就把它做成QTopia的插件了
1 把QTopia自带的例子程序(一个很简单的)的输入法加载进 qtopia.
在qtopia-free-2.1.1/examples/inputmethods/目录下有个例子程序
(1) qmake -spec $QPEDIR/mkspecs/qws/linux-generic-g++ popup.pro
(2) make
(3) 成功后目录下会自动生成libpopupim.so libpopupim.so.1 libpopupim.so.1.0 libpopupim.so.1.0.0
把生成的
libpopupim.so
libpopupim.so.1
libpopupim.so.1.0
libpopupim.so.1.0.0
安装到编译好的qtopia(qtopia的程序目录,不是编译目录)目录下的plugins/inputmethods/下
然后启动qtopia,在下面的状态栏就会出现加载好的例子输入法了 就是这个PJ
2 把自己写的输入法加载进QTopia
(1)自己写的输入法的界面类一定要实现下面规定的一个信号和一个公有构造函数,其他的成员函数自由发挥。
class GeoImDialog : public QWidget {
Q_OBJECT
signals:
void keyPress( ushort unicode, ushort keycode,ushort modifiers, bool press, bool repeat );
public:
GeoImDialog(QWidget *parent, const char *name = 0, int flags = 0);
~GeoImDialog();
void reset();
。。。。。。。。。。。。
}
(2) 然后修改下例子程序中的popupextimpl.cpp文件(这个文件实现了大部分怎么把输入法集成到QTopia的接口)
QWidget *PopupIMExtImpl::keyboardWidget( QWidget *parent, Qt::WFlags f)
{
if (!input) {
input = new GeoImDialog(自己的输入法)( parent, "SimpleInput", f );
connect(input, SIGNAL(keyPress(ushort, ushort, ushort, bool, bool)),
this, SLOT(sendKeyEvent(ushort, ushort, ushort, bool, bool)));
}
return input;
}
(3)按照上面1中的方法编译,拷贝*.so文件到qtopia/plugins目录就成功了!
老猪:写这个输入法还学到蛮多东西的,偶C++很菜,证明C++不一定要很懂才能写出具体的程序来:)因为时间原因,好多东西写的不太详细,也不想写的太详细:)有问题需要讨论的朋友留言大家一起讨论下~~