想在一个QT应用中用软键盘进行输入,于是要先研究下软键盘输入原理,幸运的是Qt4.7.0库中带有一个InputPanel的示例程序,怀着激动的心情先打开运行一遍,但发现怎么点也输入不了,于是开始仔细阅读程序和帮助,想搞清楚软键盘输入的原理以及这里是否存在bug,如果有bug那它又在哪里,怎么修改等等。
现在解释程序代码如下:
myinputpanel.h
#ifndef MYINPUTPANEL_H
#define MYINPUTPANEL_H
#include
#include
#include "ui_myinputpanelform.h"
//! [0]
class MyInputPanel : public QWidget
{
Q_OBJECT
public:
MyInputPanel();
signals:
void characterGenerated(QChar character);
protected:
bool event(QEvent *e);
private slots:
void saveFocusWidget(QWidget *oldFocus, QWidget *newFocus);
void buttonClicked(QWidget *w);
private:
Ui::MyInputPanelForm form;//输入界面对象
QWidget *lastFocusedWidget;
QSignalMapper signalMapper;
};
//! [0]
#endif // MYINPUTPANEL_H
#ifndef MYINPUTPANELCONTEXT_H
#define MYINPUTPANELCONTEXT_H
#include
#include "myinputpanel.h"
class MyInputPanel;
//! [0]
class MyInputPanelContext : public QInputContext
{
Q_OBJECT
public:
MyInputPanelContext();
~MyInputPanelContext();
bool filterEvent(const QEvent* event);
QString identifierName();
QString language();
bool isComposing() const;
void reset();
private slots:
void sendCharacter(QChar character);
private:
void updatePosition();
private:
MyInputPanel *inputPanel;
};
//! [0]
#endif // MYINPUTPANELCONTEXT_H
#include
#include
//! [main]
#include "myinputpanelcontext.h"
#include "ui_mainform.h"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyInputPanelContext *ic = new MyInputPanelContext;
app.setInputContext(ic);//设置为应用程序范围内的输入上下文
QWidget widget;
Ui::MainForm form;
form.setupUi(&widget);
widget.show();
return app.exec();
}
//! [main]
#include "myinputpanel.h"
//! [0]
MyInputPanel::MyInputPanel()
: QWidget(0, Qt::Tool | Qt::WindowStaysOnTopHint),
lastFocusedWidget(0)
{
form.setupUi(this);
//光标事件改变就更新lastFocusedWidget
connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)),
this, SLOT(saveFocusWidget(QWidget*,QWidget*)));
signalMapper.setMapping(form.panelButton_1, form.panelButton_1);
signalMapper.setMapping(form.panelButton_2, form.panelButton_2);
signalMapper.setMapping(form.panelButton_3, form.panelButton_3);
signalMapper.setMapping(form.panelButton_4, form.panelButton_4);
signalMapper.setMapping(form.panelButton_5, form.panelButton_5);
signalMapper.setMapping(form.panelButton_6, form.panelButton_6);
signalMapper.setMapping(form.panelButton_7, form.panelButton_7);
signalMapper.setMapping(form.panelButton_8, form.panelButton_8);
signalMapper.setMapping(form.panelButton_9, form.panelButton_9);
signalMapper.setMapping(form.panelButton_star, form.panelButton_star);
signalMapper.setMapping(form.panelButton_0, form.panelButton_0);
signalMapper.setMapping(form.panelButton_hash, form.panelButton_hash);
//按键到signalMapper的映射
connect(form.panelButton_1, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_2, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_3, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_4, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_5, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_6, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_7, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_8, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_9, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_star, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_0, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
connect(form.panelButton_hash, SIGNAL(clicked()),
&signalMapper, SLOT(map()));
//已映射好的signalMapper和input panel的映射
connect(&signalMapper, SIGNAL(mapped(QWidget*)),
this, SLOT(buttonClicked(QWidget*)));
}
//! [0]
bool MyInputPanel::event(QEvent *e)
{
switch (e->type()) {
//! [1]
case QEvent::WindowActivate://窗口激活事件
if (lastFocusedWidget)//如果上一次的非input panel窗口的焦点指针非零,就激动该指针的父窗口
lastFocusedWidget->activateWindow();
break;
//! [1]
default:
break;
}
return QWidget::event(e);//执行默认事件
}
//! [2]
void MyInputPanel::saveFocusWidget(QWidget * /*oldFocus*/, QWidget *newFocus)
{//判断是否是输入界面的子窗口指针,如果不是则表明是主界面的焦点指针,然后保存下来
if (newFocus != 0 && !this->isAncestorOf(newFocus)) {
lastFocusedWidget = newFocus;
}
}
//! [2]
//! [3]
void MyInputPanel::buttonClicked(QWidget *w)
{//提取属性是buttonValue这种的值,这里是按键值,并转换为char类型
QChar chr = qvariant_cast(w->property("buttonValue"));
emit characterGenerated(chr);//发射出去
}
//! [3]
#include
#include "myinputpanelcontext.h"
//#include
//! [0]
MyInputPanelContext::MyInputPanelContext()
{
inputPanel = new MyInputPanel;
connect(inputPanel, SIGNAL(characterGenerated(QChar)), SLOT(sendCharacter(QChar)));
}
//! [0]
MyInputPanelContext::~MyInputPanelContext()
{
delete inputPanel;
}
//! [1]
//事件过滤:只有面板打开和面板关闭两个函数
bool MyInputPanelContext::filterEvent(const QEvent* event)
{
if (event->type() == QEvent::RequestSoftwareInputPanel) {
updatePosition();//打开时,要更新其位置信息
inputPanel->show();//显示
return true;
} else if (event->type() == QEvent::CloseSoftwareInputPanel) {
inputPanel->hide();//隐藏
return true;
}
return false;
}
//! [1]
//返回标识符名字
QString MyInputPanelContext::identifierName()
{
return "MyInputPanelContext";
}
//复位
void MyInputPanelContext::reset()
{
}
//输入事件发送成功与否
bool MyInputPanelContext::isComposing() const
{
return true;
}
//编码方式
QString MyInputPanelContext::language()
{
return "en_US";
}
//! [2]
//发送输入字符串
void MyInputPanelContext::sendCharacter(QChar character)
{ //保护指针 /*Returns the widget that has an input focus for this input context.*/
QPointer w = focusWidget();//这个焦点应该还是有光标的LineEdit
if (!w)
return;
//按下事件
QKeyEvent keyPress(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString(character));
QApplication::sendEvent(w, &keyPress);//w为接收者,发送按下字符
if (!w)
return;//
//按键释放
QKeyEvent keyRelease(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString());
QApplication::sendEvent(w, &keyRelease);//发送释放信号
}
//! [2]
//! [3]
void MyInputPanelContext::updatePosition()
{
QWidget *widget = focusWidget();//返回有光标的窗口部件的指针,这里是两个QLineEdit窗口部件的指针
if (!widget)
return;
QRect widgetRect = widget->rect();//返回窗口部件的矩形对象
QPoint panelPos = QPoint(widgetRect.left()+10, widgetRect.bottom() + 12);//以输入光标点处的x,y坐标,来确定输入面板的放置位置信息
panelPos = widget->mapToGlobal(panelPos);//转换窗口部件中的坐标到全屏坐标中去
inputPanel->move(panelPos);//移到设置点处
}
//! [3]
#ifndef MYINPUTPANEL_H
#define MYINPUTPANEL_H
#include
#include
#include "ui_myinputpanelform.h"
//! [0]
class MyInputPanel : public QWidget
{
Q_OBJECT
public:
MyInputPanel();
QWidget *getFocusedWidget();
signals:
void characterGenerated(QChar character);
protected:
bool event(QEvent *e);
private slots:
void saveFocusWidget(QWidget *oldFocus, QWidget *newFocus);
void buttonClicked(QWidget *w);
private:
Ui::MyInputPanelForm form;
QWidget *lastFocusedWidget;
QSignalMapper signalMapper;
};
//返回主界面焦点处窗口指针 myinputpanel.cpp
QWidget * MyInputPanel::getFocusedWidget()
{
return lastFocusedWidget;
}
void MyInputPanelContext::sendCharacter(QChar character)
{
// QPointer w = focusWidget();
QPointer w = inputPanel->getFocusedWidget();
if (!w)
return;
QKeyEvent keyPress(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString(character));
QApplication::sendEvent(w, &keyPress);//w为事件接收者
if (!w)
return;//
QKeyEvent keyRelease(QEvent::KeyPress, character.unicode(), Qt::NoModifier, QString());
QApplication::sendEvent(w, &keyRelease);
}
转载自:http://xl028.blog.163.com/blog/static/19973024220127276110749/