QT 軟件鍵盤及動態屬性



 轉載自:http://xl028.blog.163.com/blog/static/1997302422012728113519978/


根據qt中自帶inputpanel實例,自己重寫該過程,並詳細分析過程及注意事項。

  新建,GUI應用,基類Qwidget,主界面簡單拖入幾個有輸入功能的部件。

軟件鍵盤及動態屬性 - 直到永遠 - 直到永遠的博客
  繼續,新建UI類MyInputpanel,基類選QWidget
myinputpanel.h

#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函數,不然這個類將不能被使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章