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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值