转载自:http://xl028.blog.163.com/blog/static/1997302422012728113519978/
根据qt中自带inputpanel实例,自己重写该过程,并详细分析过程及注意事项。
新建,GUI应用,基类Qwidget,主界面简单拖入几个有输入功能的部件。
#ifndef MYINPUTPANEL_H #define MYINPUTPANEL_H
#include <QtGui> #include <QWidget>
namespace Ui { class MyInputPanel; }
class MyInputPanel : public QWidget { Q_OBJECT public: MyInputPanel(); QWidget *getFocusedWidget();//获取有光标且需要输入的窗口指针 signals: void characterGenerated(QChar character);//字符产生,每个按键都要对应一个ASCII
protected://事件处理函数,这里只处理窗口激活事件,其它事件lfyw bool event(QEvent *e);
private slots://保存上次要输入窗口的指针 void saveFocusWidget(QWidget *oldFocus, QWidget *newFocus); void buttonClicked(QWidget *w);
private: Ui::MyInputPanel *ui; QWidget *lastFocusedWidget; QSignalMapper signalMapper;//多信号的映射 };
#endif // MYINPUTPANEL_H
myinputpanel.cpp
#include "myinputpanel.h" #include "ui_myinputpanelform.h"
MyInputPanel::MyInputPanel() : QWidget(0, Qt::Tool | Qt::WindowStaysOnTopHint), //工具窗口 lastFocusedWidget(0), ui(new Ui::MyInputPanel) { ui->setupUi(this); //连接应用程序的光标改变信号与saveFocusWidget connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(saveFocusWidget(QWidget*,QWidget*))); //用setMapping函数将各按键与特殊的字符串或整数建立映射, //这里是ui->panelButton_0和其自身这种整数建立映射, //这种特殊的整数在map函数重新发送各信号的时候有用 signalMapper.setMapping(ui->panelButton_0, ui->panelButton_0); signalMapper.setMapping(ui->panelButton_1, ui->panelButton_1); signalMapper.setMapping(ui->panelButton_2, ui->panelButton_2); signalMapper.setMapping(ui->panelButton_3, ui->panelButton_3); signalMapper.setMapping(ui->panelButton_4, ui->panelButton_4); signalMapper.setMapping(ui->panelButton_5, ui->panelButton_5); signalMapper.setMapping(ui->panelButton_6, ui->panelButton_6); signalMapper.setMapping(ui->panelButton_7, ui->panelButton_7); signalMapper.setMapping(ui->panelButton_8, ui->panelButton_8); signalMapper.setMapping(ui->panelButton_9, ui->panelButton_9); signalMapper.setMapping(ui->panelButton_star, ui->panelButton_star); signalMapper.setMapping(ui->panelButton_hash, ui->panelButton_hash); //再将各按键对象和map函数建立信号与槽的关系 connect(ui->panelButton_0, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_1, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_2, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_3, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_4, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_5, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_6, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_7, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_8, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_9, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_star, SIGNAL(clicked()), &signalMapper, SLOT(map())); connect(ui->panelButton_hash, SIGNAL(clicked()), &signalMapper, SLOT(map())); //再与将signalMapper与buttonClicked连接 //总的说来有以上三个步骤,最后形成多对一的映射 connect(&signalMapper, SIGNAL(mapped(QWidget*)), this, SLOT(buttonClicked(QWidget*))); }
bool MyInputPanel::event(QEvent *e) { switch (e->type()) { //! [1] case QEvent::WindowActivate: if (lastFocusedWidget)//激活最后一次有光标的窗口 lastFocusedWidget->activateWindow(); break; //! [1] default: break; }
return QWidget::event(e);//其它事件默认,必须要有 }
//! [2]
void MyInputPanel::saveFocusWidget(QWidget * /*oldFocus*/, QWidget *newFocus) { //如果非零,且不是输入面板inputpanel对象的子部件指针就保存 //这里只保存需要输入窗口中的指针 if (newFocus != 0 && !this->isAncestorOf(newFocus)) { lastFocusedWidget = newFocus; qDebug() <<"FocusWidget Changed" << endl;// } }
void MyInputPanel::buttonClicked(QWidget *w) { //property函数返回属性为lylbuttonValue的对应值,这里为每个按键对应的ASCII //qvariant_cast(T)(value)将输入值value转换为T类型 QChar chr = qvariant_cast<QChar>(w->property("lylbuttonValue")); // chr = '1'; qDebug() << "chr:" <<chr <<endl;// emit characterGenerated(chr);//将按键的ASCII码发送出去 }
//返回主界面焦点处窗口指针 QWidget * MyInputPanel::getFocusedWidget() { return lastFocusedWidget; }
myinputpanelform.ui注意:focusPolicy要选Nofocus,还有其动态属性,一会再说新建输入上下文类,基类QInputContextmyinputpanelcontext.h#ifndef MYINPUTPANELCONTEXT_H #define MYINPUTPANELCONTEXT_H
#include <QInputContext> //#include "myinputpanel.h" class MyInputPanel;
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; };
#endif // MYINPUTPANELCONTEXT_H
myinputpanelcontext.cpp#include "myinputpanelcontext.h" #include "myinputpanel.h" #include <QDebug>
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 false; }
QString MyInputPanelContext::language() { return "en_US"; }
//! [2]
void MyInputPanelContext::sendCharacter(QChar character) { // QPointer<QWidget> w = focusWidget(); //获取输入窗口指针 QPointer<QWidget> w = inputPanel->getFocusedWidget();
if (!w) return; qDebug() << "kk"<<endl; //发送按键值直接到输入窗口 //QKeyEvent参数:按键类型,编码,修饰符,最后才是发送值 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);//移到设置点处 }
最后,main.cpp#include <QtGui/QApplication> #include "widget.h" #include "myinputpanelcontext.h"
int main(int argc, char *argv[]) { QApplication a(argc, argv); MyInputPanelContext *ic = new MyInputPanelContext; a.setInputContext(ic);//将输入上下文与应用程序关联
Widget w; w.show(); return a.exec(); }
编译,运行,但是,还是不能输入,这里就有一点了,那就是按键动态属性的问题了。也就是说,我们需要自己设定按键对应的ASCII码值,于是在ui_myinputpanelform.h修改如下:
/******************************************************************************** ** Form generated from reading UI file 'myinputpanelform.ui' ** ** Created: Tue Aug 28 09:56:41 2012 ** by: Qt User Interface Compiler version 4.7.0 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/
#ifndef UI_MYINPUTPANELFORM_H #define UI_MYINPUTPANELFORM_H
#include <QtCore/QVariant> #include <QtGui/QAction> #include <QtGui/QApplication> #include <QtGui/QButtonGroup> #include <QtGui/QGridLayout> #include <QtGui/QHBoxLayout> #include <QtGui/QHeaderView> #include <QtGui/QPushButton> #include <QtGui/QSpacerItem> #include <QtGui/QVBoxLayout> #include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MyInputPanel { public: QWidget *widget; QVBoxLayout *verticalLayout; QGridLayout *gridLayout; QPushButton *panelButton_1; QPushButton *panelButton_2; QPushButton *panelButton_3; QPushButton *panelButton_4; QPushButton *panelButton_5; QPushButton *panelButton_6; QPushButton *panelButton_7; QPushButton *panelButton_8; QPushButton *panelButton_9; QPushButton *panelButton_star; QPushButton *panelButton_0; QPushButton *panelButton_hash; QHBoxLayout *horizontalLayout; QSpacerItem *horizontalSpacer; QPushButton *closeBtn;
void setupUi(QWidget *MyInputPanel) { if (MyInputPanel->objectName().isEmpty()) MyInputPanel->setObjectName(QString::fromUtf8("MyInputPanel")); MyInputPanel->resize(225, 255); widget = new QWidget(MyInputPanel); widget->setObjectName(QString::fromUtf8("widget")); widget->setGeometry(QRect(10, 10, 201, 231)); verticalLayout = new QVBoxLayout(widget); verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); verticalLayout->setContentsMargins(0, 0, 0, 0); gridLayout = new QGridLayout(); gridLayout->setObjectName(QString::fromUtf8("gridLayout")); panelButton_1 = new QPushButton(widget); panelButton_1->setObjectName(QString::fromUtf8("panelButton_1")); QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(panelButton_1->sizePolicy().hasHeightForWidth()); panelButton_1->setSizePolicy(sizePolicy); panelButton_1->setMinimumSize(QSize(45, 40)); panelButton_1->setFocusPolicy(Qt::NoFocus);
//加入动态属性 panelButton_1->setProperty("lylbuttonValue",QVariant(QChar('0' + 1)));
gridLayout->addWidget(panelButton_1, 0, 0, 1, 1);
panelButton_2 = new QPushButton(widget); panelButton_2->setObjectName(QString::fromUtf8("panelButton_2")); sizePolicy.setHeightForWidth(panelButton_2->sizePolicy().hasHeightForWidth()); panelButton_2->setSizePolicy(sizePolicy); panelButton_2->setMinimumSize(QSize(45, 40)); panelButton_2->setFocusPolicy(Qt::NoFocus); panelButton_2->setProperty("lylbuttonValue",QVariant(QChar('0' + 2)));
gridLayout->addWidget(panelButton_2, 0, 1, 1, 1);
panelButton_3 = new QPushButton(widget); panelButton_3->setObjectName(QString::fromUtf8("panelButton_3")); sizePolicy.setHeightForWidth(panelButton_3->sizePolicy().hasHeightForWidth()); panelButton_3->setSizePolicy(sizePolicy); panelButton_3->setMinimumSize(QSize(45, 40)); panelButton_3->setFocusPolicy(Qt::NoFocus); panelButton_3->setProperty("lylbuttonValue",QVariant(QChar('0' + 3)));
gridLayout->addWidget(panelButton_3, 0, 2, 1, 1);
panelButton_4 = new QPushButton(widget); panelButton_4->setObjectName(QString::fromUtf8("panelButton_4")); sizePolicy.setHeightForWidth(panelButton_4->sizePolicy().hasHeightForWidth()); panelButton_4->setSizePolicy(sizePolicy); panelButton_4->setMinimumSize(QSize(45, 40)); panelButton_4->setFocusPolicy(Qt::NoFocus); panelButton_4->setProperty("lylbuttonValue",QVariant(QChar('0' + 4)));
gridLayout->addWidget(panelButton_4, 1, 0, 1, 1);
panelButton_5 = new QPushButton(widget); panelButton_5->setObjectName(QString::fromUtf8("panelButton_5")); sizePolicy.setHeightForWidth(panelButton_5->sizePolicy().hasHeightForWidth()); panelButton_5->setSizePolicy(sizePolicy); panelButton_5->setMinimumSize(QSize(45, 40)); panelButton_5->setFocusPolicy(Qt::NoFocus); panelButton_5->setProperty("lylbuttonValue",QVariant(QChar('0' + 5)));
gridLayout->addWidget(panelButton_5, 1, 1, 1, 1);
panelButton_6 = new QPushButton(widget); panelButton_6->setObjectName(QString::fromUtf8("panelButton_6")); sizePolicy.setHeightForWidth(panelButton_6->sizePolicy().hasHeightForWidth()); panelButton_6->setSizePolicy(sizePolicy); panelButton_6->setMinimumSize(QSize(45, 40)); panelButton_6->setFocusPolicy(Qt::NoFocus); panelButton_6->setProperty("lylbuttonValue",QVariant(QChar('0' + 6)));
gridLayout->addWidget(panelButton_6, 1, 2, 1, 1);
panelButton_7 = new QPushButton(widget); panelButton_7->setObjectName(QString::fromUtf8("panelButton_7")); sizePolicy.setHeightForWidth(panelButton_7->sizePolicy().hasHeightForWidth()); panelButton_7->setSizePolicy(sizePolicy); panelButton_7->setMinimumSize(QSize(45, 40)); panelButton_7->setFocusPolicy(Qt::NoFocus); panelButton_7->setProperty("lylbuttonValue",QVariant(QChar('0' + 7)));
gridLayout->addWidget(panelButton_7, 2, 0, 1, 1);
panelButton_8 = new QPushButton(widget); panelButton_8->setObjectName(QString::fromUtf8("panelButton_8")); sizePolicy.setHeightForWidth(panelButton_8->sizePolicy().hasHeightForWidth()); panelButton_8->setSizePolicy(sizePolicy); panelButton_8->setMinimumSize(QSize(45, 40)); panelButton_8->setFocusPolicy(Qt::NoFocus); panelButton_8->setProperty("lylbuttonValue",QVariant(QChar('0' + 8)));
gridLayout->addWidget(panelButton_8, 2, 1, 1, 1);
panelButton_9 = new QPushButton(widget); panelButton_9->setObjectName(QString::fromUtf8("panelButton_9")); sizePolicy.setHeightForWidth(panelButton_9->sizePolicy().hasHeightForWidth()); panelButton_9->setSizePolicy(sizePolicy); panelButton_9->setMinimumSize(QSize(45, 40)); panelButton_9->setFocusPolicy(Qt::NoFocus); panelButton_9->setProperty("lylbuttonValue",QVariant(QChar('0' + 9)));
gridLayout->addWidget(panelButton_9, 2, 2, 1, 1);
panelButton_star = new QPushButton(widget); panelButton_star->setObjectName(QString::fromUtf8("panelButton_star")); sizePolicy.setHeightForWidth(panelButton_star->sizePolicy().hasHeightForWidth()); panelButton_star->setSizePolicy(sizePolicy); panelButton_star->setMinimumSize(QSize(45, 40)); panelButton_star->setFocusPolicy(Qt::NoFocus); panelButton_star->setProperty("lylbuttonValue",QVariant(QChar(42)));
gridLayout->addWidget(panelButton_star, 3, 0, 1, 1);
panelButton_0 = new QPushButton(widget); panelButton_0->setObjectName(QString::fromUtf8("panelButton_0")); sizePolicy.setHeightForWidth(panelButton_0->sizePolicy().hasHeightForWidth()); panelButton_0->setSizePolicy(sizePolicy); panelButton_0->setMinimumSize(QSize(45, 40)); panelButton_0->setFocusPolicy(Qt::NoFocus); panelButton_0->setProperty("lylbuttonValue",QVariant(QChar('0' + 0)));
gridLayout->addWidget(panelButton_0, 3, 1, 1, 1);
panelButton_hash = new QPushButton(widget); panelButton_hash->setObjectName(QString::fromUtf8("panelButton_hash")); sizePolicy.setHeightForWidth(panelButton_hash->sizePolicy().hasHeightForWidth()); panelButton_hash->setSizePolicy(sizePolicy); panelButton_hash->setMinimumSize(QSize(45, 40)); panelButton_hash->setFocusPolicy(Qt::NoFocus); panelButton_hash->setProperty("lylbuttonValue",QVariant(QChar(35)));
gridLayout->addWidget(panelButton_hash, 3, 2, 1, 1);
verticalLayout->addLayout(gridLayout);
horizontalLayout = new QHBoxLayout(); horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer);
closeBtn = new QPushButton(widget); closeBtn->setObjectName(QString::fromUtf8("closeBtn")); closeBtn->setFocusPolicy(Qt::NoFocus);
horizontalLayout->addWidget(closeBtn);
verticalLayout->addLayout(horizontalLayout);
retranslateUi(MyInputPanel); QObject::connect(closeBtn, SIGNAL(clicked()), MyInputPanel, SLOT(hide()));
QMetaObject::connectSlotsByName(MyInputPanel); } // setupUi
void retranslateUi(QWidget *MyInputPanel) { MyInputPanel->setWindowTitle(QApplication::translate("MyInputPanel", "Soft_keyboard", 0, QApplication::UnicodeUTF8)); panelButton_1->setText(QApplication::translate("MyInputPanel", "1", 0, QApplication::UnicodeUTF8)); panelButton_2->setText(QApplication::translate("MyInputPanel", "2", 0, QApplication::UnicodeUTF8)); panelButton_3->setText(QApplication::translate("MyInputPanel", "3", 0, QApplication::UnicodeUTF8)); panelButton_4->setText(QApplication::translate("MyInputPanel", "4", 0, QApplication::UnicodeUTF8)); panelButton_5->setText(QApplication::translate("MyInputPanel", "5", 0, QApplication::UnicodeUTF8)); panelButton_6->setText(QApplication::translate("MyInputPanel", "6", 0, QApplication::UnicodeUTF8)); panelButton_7->setText(QApplication::translate("MyInputPanel", "7", 0, QApplication::UnicodeUTF8)); panelButton_8->setText(QApplication::translate("MyInputPanel", "8", 0, QApplication::UnicodeUTF8)); panelButton_9->setText(QApplication::translate("MyInputPanel", "9", 0, QApplication::UnicodeUTF8)); panelButton_star->setText(QApplication::translate("MyInputPanel", "\357\274\212", 0, QApplication::UnicodeUTF8)); panelButton_0->setText(QApplication::translate("MyInputPanel", "0", 0, QApplication::UnicodeUTF8)); panelButton_hash->setText(QApplication::translate("MyInputPanel", "\357\274\203", 0, QApplication::UnicodeUTF8)); closeBtn->setText(QApplication::translate("MyInputPanel", "close", 0, QApplication::UnicodeUTF8)); } // retranslateUi
};
namespace Ui { class MyInputPanel: public Ui_MyInputPanel {}; } // namespace Ui
QT_END_NAMESPACE
#endif // UI_MYINPUTPANELFORM_H
总的,工程结构如下:
注意:软件键上面的按钮一定不能有焦点(NoFocus),这样,可以维持焦点在需要被输入的窗口上面
另外,很重要的一点!
这里QInputContext为抽象基类,为什么这样说呢?因为它含有纯虚函数(我们知道虚函数,意思说可以在派生类中重新定义扩展的函数,而纯虚函数,则只具函数名,没有函数体,不能被调用,只是在哪占了个位置,留着给派生类来继承定义的)都是抽象类,而这里QInputContext类刚好有void QInputContext::reset () [pure virtual]纯虚函数,抽象类不能被实例化,即不能用来定义对象!主要原因是里面的纯虚函数不能被调用!
所以这里MyInputPanelContext里面必须重新定义其基类的一定虚函数,特别是reset函数,不然这个类将不能被使用。