• 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", "357274212", 0, QApplication::UnicodeUTF8));         panelButton_0->setText(QApplication::translate("MyInputPanel", "0", 0, QApplication::UnicodeUTF8));         panelButton_hash->setText(QApplication::translate("MyInputPanel", "357274203", 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函数,不然这个类将不能被使用。

  • 相关阅读:
    使用canvas实现擦玻璃效果
    安装jdk For Windows
    墙裂推荐4款js网页烟花特效
    再次推荐一款逼真的HTML5下雪效果
    HTML5播放暂停音乐
    周末web前端练习
    Javascript贪食蛇小游戏
    jquery实现更多内容效果
    jQuery省市区三级联动插件
    Web前端测试题
  • 原文地址:https://www.cnblogs.com/sggggr/p/12733373.html
Copyright © 2020-2023  润新知