zoukankan      html  css  js  c++  java
  • Qt全平台虚拟键盘

        一、开发环境


        PC机:QT5.6.2,XP系统,QT Creator4.1

        嵌入式硬件平台:TQ210核心板,板载S5PV210芯片

        嵌入式软件平台:Linux3.10.46内核,UBOOT移植的是2014.12版本

    二、资源简介
        Qt5取消了QInputContext类后,以前在QT4.8.5上用的软键盘代码不能用了,在网上找到了大神刘典武的软键盘核心代码,经过修改可以在QT5.6上用了,嵌入式ARM平台上也试验可用。

    三、源码简介
    头文件定义如下:

    #ifndef KEYBOARD_H
    #define KEYBOARD_H
    
    #include <QWidget>
    class QStackedWidget;
    class QLabel;
    class QLineEdit;
    class QPushButton;
    class QComboBox;
    
    // 按钮的边长,键盘总长度=14*BTN_SIZE,键盘总宽度=3*BTN_SIZE
    #define BTN_SIZE    40
    
    class keyBoard : public QWidget
    {
        Q_OBJECT
    public:
        explicit keyBoard(QWidget *parent = 0);
        ~keyBoard();
    
    protected:
        void mouseMoveEvent(QMouseEvent *e);
        void mousePressEvent(QMouseEvent *e);
        void mouseReleaseEvent(QMouseEvent *);
    
    private slots:
        void focusChanged(QWidget *, QWidget *nowWidget);
        void slotBtnClicked();         // 按键处理
    
    private:
        int deskWidth;                  //桌面宽度
        int deskHeight;                 //桌面高度
        int frmWidth;                   //窗体宽度
        int frmHeight;                  //窗体高度
    
        QPoint mousePoint;              //鼠标拖动自定义标题栏时的坐标
        bool mousePressed;              //鼠标是否按下
        void InitWindow();              //初始化无边框窗体
        void InitForm();                //初始化窗体数据
    
        QLineEdit *currentLineEdit;     //当前焦点的文本框
        QString currentType;            //当前输入法类型
        void changeType(QString type);  //改变输入法类型
        void changeLetter(bool isUpper);//改变字母大小写
        void changeStyle(int style);    //切换样式处理
        void setStyle(QString topColor,QString bottomColor,QString borderColor,QString textColor);
    
        int currentStyle;
    
        QStackedWidget *keyWindow;      // 键盘窗口,可以翻页显示
        QWidget *letterWindow;          // 字母键盘
        QWidget *signWindow;            // 字母键盘
        QLabel *infoLabel;              // 显示键盘信息
    
        QPushButton *closeBtn;
        QPushButton *delBtn;
        QPushButton *typeBtn;
        QPushButton *styleBtn;
    
        QPushButton *btn0;
        ...
        QPushButton *btn9;
    
        QPushButton *btnA;
        ...
        QPushButton *btnZ;
    
        QPushButton *btnSign0;
        ...
        QPushButton *btnSign12;
    };
    
    #endif // KEYBOARD_H

    头文件中主要是定义了键盘的几个界面:数字、字母、字符界面
    还定义的所有的按钮:数字、字母、字符按钮
    鼠标相关的操作函数,是为了实现键盘界面的拖动
    最核心的代码是两个槽函数:focusChanged、slotBtnClicked(),分别是处理焦点和按钮事件
    其中,BTN_SIZE是每个按钮的边长,在编译之前可以更改,默认是40

    cpp文件核心代码如下:
    1、构造函数
    keyBoard::keyBoard(QWidget *parent) :
        QWidget(parent)
    {
        this->InitWindow();
        this->InitForm();
    
        QDesktopWidget* w = QApplication::desktop();
        deskWidth = w->screenGeometry().width();
        deskHeight = w->screenGeometry().height();
        frmWidth = this->width();
        frmHeight = this->height();
    }

    首先,调用了初始化界面布局和私有数据函数,然后获取显示设备的分辩率

    2、初始化界面布局函数

    void keyBoard::InitWindow()
    {
        this->setProperty("Form", true);
        this->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
        this->setFixedSize(14 * BTN_SIZE, 3 * BTN_SIZE);
        this->setFocusPolicy(Qt::NoFocus);
    
        keyWindow = new QStackedWidget(this);
        keyWindow->setFixedSize(13 * BTN_SIZE, 2 * BTN_SIZE);
        letterWindow = new QWidget;
        signWindow = new QWidget;
    
        // 填加功能按钮
        closeBtn = new QPushButton(this);
        closeBtn->setObjectName("closeBtn");
        closeBtn->setProperty("function", true);
        closeBtn->setText(tr("X"));
        closeBtn->setFixedSize(BTN_SIZE, BTN_SIZE);
    
        // 删除一个字符
        delBtn = new QPushButton(this);
        delBtn->setObjectName("delBtn");
        delBtn->setProperty("function", true);
        delBtn->setText(tr("D"));
        delBtn->setFixedSize(BTN_SIZE, BTN_SIZE);
    
        // 改变输法类型:大写,小写,字符
        typeBtn = new QPushButton(this);
        typeBtn->setObjectName("typeBtn");
        typeBtn->setProperty("function", true);
        typeBtn->setText(tr(""));
        typeBtn->setFixedSize(BTN_SIZE, BTN_SIZE);
    
        // 换肤
        styleBtn = new QPushButton(this);
        styleBtn->setObjectName("styleBtn");
        styleBtn->setProperty("function", true);
        styleBtn->setText(tr("style"));
        styleBtn->setFixedSize(BTN_SIZE, BTN_SIZE);
    
        // 填加数字键盘
        btn1 = new QPushButton(this);
        btn1->setText(tr("1"));
        btn1->setProperty("num", true);
        btn1->setFixedSize(BTN_SIZE, BTN_SIZE);
    
    。。。。。。
    
        layout->addWidget(delBtn,   0,11,1,1);
        layout->addWidget(closeBtn, 0,12,1,1);
        layout->addWidget(typeBtn,  1,13,1,1);
        layout->addWidget(styleBtn, 2,13,1,1);
        layout->addWidget(keyWindow,1,0,2,13);
        layout->setSpacing(0);
        layout->setContentsMargins(0, 0, 0, 0);
        this->setLayout(layout);
    }
    首先,设定了键盘界面的尺寸,然后具体定义了所有控件,最后给界面布局。
     
    3、初始化数据函数
    void keyBoard::InitForm()
    {
        currentStyle = 0;
        currentLineEdit = 0;
        mousePressed = false;
        currentType = "min";
        changeType("min");
        currentStyle = 0;
        changeStyle(currentStyle);
    
        QList<QPushButton *> btn = this->findChildren<QPushButton *>();
        foreach (QPushButton * b, btn) {
            connect(b, SIGNAL(clicked()), this, SLOT(slotBtnClicked()));
        }
    
        // 绑定全局改变焦点信号槽
        connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)),
                this, SLOT(focusChanged(QWidget *, QWidget *)));
    }
    首先,初始化私有数据,然后把所有按钮都邦定按钮处理槽函数,最后绑定全局焦点改变时的处理函数,这个函数也是呼出键盘的核心。
     
    4、焦点处理函数
    void keyBoard::focusChanged(QWidget *, QWidget *nowWidget)
    {
        if (nowWidget != 0 && !this->isAncestorOf(nowWidget))
        {
            if (nowWidget->inherits("QLineEdit"))
            {
                currentLineEdit = (QLineEdit *)nowWidget;
    
                QPoint movePoint;
    
                // 鼠标点击位置坐标
                if (QCursor::pos().y() > deskHeight / 2)
                {
                    // 靠上居中显示
                    movePoint = QPoint(deskWidth/2 - frmWidth/2, 0);
                }
                else
                {
                    // 靠下居中显示
                    movePoint = QPoint(deskWidth/2 - frmWidth/2, deskHeight - frmHeight);
                }
    
                this->move(movePoint);
                this->repaint();
                this->setVisible(true);
            }
            else
            {
                currentLineEdit = 0;
                //qDebug() << "BBB";
                this->setVisible(false);
                // 需要将输入法切换到最初的原始状态--小写
                currentType="min";
                changeType(currentType);
                currentStyle = 0;
                changeStyle(currentStyle);
                keyWindow->setCurrentIndex(0);
            }
        }
    }
    首先,判断当前焦点是否在QLineEdit控件中,然后根据焦点的坐标,显示键盘的位置。
     5、按键处理函数
    void keyBoard::slotBtnClicked()
    {
        QPushButton *btn = (QPushButton *)sender();
        QString objectName = btn->objectName();
    
        if (objectName == "typeBtn")
        {
            if (currentType == "min")
            {
                currentType = "max";
            }
            else if (currentType == "max")
            {
                currentType = "sign";
            }
            else
            {
                currentType = "min";
            }
            changeType(currentType);
        }
        else if (objectName == "delBtn")
    
    。。。。。。
    
        else
        {
            QString value = btn->text();
            // 如果是&按钮,因为对应&被过滤,所以真实的text为去除前面一个&字符
            if (value == "&&")
            {
                value = value.right(1);
            }
            // 当前不是中文模式,则单击按钮对应text为传递参数
            if (currentType != "chinese")
            {
                if (currentLineEdit != 0)
                {
                    currentLineEdit->insert(value);
                }
            }
        }
    }

    根据按键的objectName区分不同的按键,进行相应的处理。

    6、主函数调用方法

    #include "keyBoard.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        keyBoard keyBoard;
        keyBoard.hide();
    
        MainWindow w;
        w.show();
    
        return a.exec();
    }

    只需填加头文件定义,然后在main函数里实例化就可以了。

    四、效果

     

     

     

    五、总结   
        程序是在QT5.6的环境下编写的,理论上来说,QT4也可以运行,但我没试验。在PC机和ARM嵌入式开发板都可以完美运行。
    此虚拟键盘程序只包含两个文件,可以非常方便的加入到现有的工程当中。 


    程序完整源码见附件。
    http://download.csdn.net/download/wzs250969969/10050991
    ————————————————
    版权声明:本文为CSDN博主「急行的小船」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/wzs250969969/article/details/78418725

  • 相关阅读:
    虚拟机磁盘文件丢失如何通过拼数据库碎片的方式恢复
    存储设备IBM DS5020故障离线怎么办
    RAID6存储阵列故障oracle数据库碎片恢复
    Raid磁盘阵列重建后如何恢复原来的数据
    服务器断电Oracle数据库修复数据过程
    Linux新手随手笔记2.3-使用Bind提供域名解析服务
    Linux新手随手笔记2.2-使用Samba和NFS实现文件共享
    Linux新手随手笔记2.1-ftp
    Linux新手随手笔记1.9-使用Apache搭建网站
    Linux新手随手笔记1.8-配置网卡
  • 原文地址:https://www.cnblogs.com/sggggr/p/12733133.html
Copyright © 2011-2022 走看看