轉載自: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,還有其動態屬性,一會再說
新建輸入上下文類,基類QInputContext
myinputpanelcontext.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函數,不然這個類將不能被使用。