inputpanel实例分析(年代久远,排版混乱但是不影响理解,好文)

根据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函数,不然这个类将不能被使用。

猜你喜欢

转载自www.cnblogs.com/sggggr/p/12733373.html