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平台上也试验可用。

三、源码简介

头文件定义如下:
[plain] view plain copy
  1. #ifndef KEYBOARD_H  
  2. #define KEYBOARD_H  
  3.   
  4. #include <QWidget>  
  5. class QStackedWidget;  
  6. class QLabel;  
  7. class QLineEdit;  
  8. class QPushButton;  
  9. class QComboBox;  
  10.   
  11. // 按钮的边长,键盘总长度=14*BTN_SIZE,键盘总宽度=3*BTN_SIZE  
  12. #define BTN_SIZE    40  
  13.   
  14. class keyBoard : public QWidget  
  15. {  
  16.     Q_OBJECT  
  17. public:  
  18.     explicit keyBoard(QWidget *parent = 0);  
  19.     ~keyBoard();  
  20.   
  21. protected:  
  22.     void mouseMoveEvent(QMouseEvent *e);  
  23.     void mousePressEvent(QMouseEvent *e);  
  24.     void mouseReleaseEvent(QMouseEvent *);  
  25.   
  26. private slots:  
  27.     void focusChanged(QWidget *, QWidget *nowWidget);  
  28.     void slotBtnClicked();         // 按键处理  
  29.   
  30. private:  
  31.     int deskWidth;                  //桌面宽度  
  32.     int deskHeight;                 //桌面高度  
  33.     int frmWidth;                   //窗体宽度  
  34.     int frmHeight;                  //窗体高度  
  35.   
  36.     QPoint mousePoint;              //鼠标拖动自定义标题栏时的坐标  
  37.     bool mousePressed;              //鼠标是否按下  
  38.     void InitWindow();              //初始化无边框窗体  
  39.     void InitForm();                //初始化窗体数据  
  40.   
  41.     QLineEdit *currentLineEdit;     //当前焦点的文本框  
  42.     QString currentType;            //当前输入法类型  
  43.     void changeType(QString type);  //改变输入法类型  
  44.     void changeLetter(bool isUpper);//改变字母大小写  
  45.     void changeStyle(int style);    //切换样式处理  
  46.     void setStyle(QString topColor,QString bottomColor,QString borderColor,QString textColor);  
  47.   
  48.     int currentStyle;  
  49.   
  50.     QStackedWidget *keyWindow;      // 键盘窗口,可以翻页显示  
  51.     QWidget *letterWindow;          // 字母键盘  
  52.     QWidget *signWindow;            // 字母键盘  
  53.     QLabel *infoLabel;              // 显示键盘信息  
  54.   
  55.     QPushButton *closeBtn;  
  56.     QPushButton *delBtn;  
  57.     QPushButton *typeBtn;  
  58.     QPushButton *styleBtn;  
  59.   
  60.     QPushButton *btn0;  
  61.     ...  
  62.     QPushButton *btn9;  
  63.   
  64.     QPushButton *btnA;  
  65.     ...  
  66.     QPushButton *btnZ;  
  67.   
  68.     QPushButton *btnSign0;  
  69.     ...  
  70.     QPushButton *btnSign12;  
  71. };  
  72.   
  73. #endif // KEYBOARD_H  



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

cpp文件核心代码如下:
1、构造函数
[plain] view plain copy
  1. keyBoard::keyBoard(QWidget *parent) :  
  2.     QWidget(parent)  
  3. {  
  4.     this->InitWindow();  
  5.     this->InitForm();  
  6.   
  7.     QDesktopWidget* w = QApplication::desktop();  
  8.     deskWidth = w->screenGeometry().width();  
  9.     deskHeight = w->screenGeometry().height();  
  10.     frmWidth = this->width();  
  11.     frmHeight = this->height();  
  12. }  

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

2、初始化界面布局函数
[plain] view plain copy
  1. void keyBoard::InitWindow()  
  2. {  
  3.     this->setProperty("Form", true);  
  4.     this->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);  
  5.     this->setFixedSize(14 * BTN_SIZE, 3 * BTN_SIZE);  
  6.     this->setFocusPolicy(Qt::NoFocus);  
  7.   
  8.     keyWindow = new QStackedWidget(this);  
  9.     keyWindow->setFixedSize(13 * BTN_SIZE, 2 * BTN_SIZE);  
  10.     letterWindow = new QWidget;  
  11.     signWindow = new QWidget;  
  12.   
  13.     // 填加功能按钮  
  14.     closeBtn = new QPushButton(this);  
  15.     closeBtn->setObjectName("closeBtn");  
  16.     closeBtn->setProperty("function", true);  
  17.     closeBtn->setText(tr("X"));  
  18.     closeBtn->setFixedSize(BTN_SIZE, BTN_SIZE);  
  19.   
  20.     // 删除一个字符  
  21.     delBtn = new QPushButton(this);  
  22.     delBtn->setObjectName("delBtn");  
  23.     delBtn->setProperty("function", true);  
  24.     delBtn->setText(tr("D"));  
  25.     delBtn->setFixedSize(BTN_SIZE, BTN_SIZE);  
  26.   
  27.     // 改变输法类型:大写,小写,字符  
  28.     typeBtn = new QPushButton(this);  
  29.     typeBtn->setObjectName("typeBtn");  
  30.     typeBtn->setProperty("function", true);  
  31.     typeBtn->setText(tr("小"));  
  32.     typeBtn->setFixedSize(BTN_SIZE, BTN_SIZE);  
  33.   
  34.     // 换肤  
  35.     styleBtn = new QPushButton(this);  
  36.     styleBtn->setObjectName("styleBtn");  
  37.     styleBtn->setProperty("function", true);  
  38.     styleBtn->setText(tr("style"));  
  39.     styleBtn->setFixedSize(BTN_SIZE, BTN_SIZE);  
  40.   
  41.     // 填加数字键盘  
  42.     btn1 = new QPushButton(this);  
  43.     btn1->setText(tr("1"));  
  44.     btn1->setProperty("num", true);  
  45.     btn1->setFixedSize(BTN_SIZE, BTN_SIZE);  
  46.   
  47. 。。。。。。  
  48.   
  49.     layout->addWidget(delBtn,   0,11,1,1);  
  50.     layout->addWidget(closeBtn, 0,12,1,1);  
  51.     layout->addWidget(typeBtn,  1,13,1,1);  
  52.     layout->addWidget(styleBtn, 2,13,1,1);  
  53.     layout->addWidget(keyWindow,1,0,2,13);  
  54.     layout->setSpacing(0);  
  55.     layout->setContentsMargins(0, 0, 0, 0);  
  56.     this->setLayout(layout);  
  57. }  

首先,设定了键盘界面的尺寸,然后具体定义了所有控件,最后给界面布局。

3、初始化数据函数
[plain] view plain copy
  1. void keyBoard::InitForm()  
  2. {  
  3.     currentStyle = 0;  
  4.     currentLineEdit = 0;  
  5.     mousePressed = false;  
  6.     currentType = "min";  
  7.     changeType("min");  
  8.     currentStyle = 0;  
  9.     changeStyle(currentStyle);  
  10.   
  11.     QList<QPushButton *> btn = this->findChildren<QPushButton *>();  
  12.     foreach (QPushButton * b, btn) {  
  13.         connect(b, SIGNAL(clicked()), this, SLOT(slotBtnClicked()));  
  14.     }  
  15.   
  16.     // 绑定全局改变焦点信号槽  
  17.     connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)),  
  18.             this, SLOT(focusChanged(QWidget *, QWidget *)));  
  19. }  

首先,初始化私有数据,然后把所有按钮都邦定按钮处理槽函数,最后绑定全局焦点改变时的处理函数,这个函数也是呼出键盘的核心。

4、焦点处理函数
[plain] view plain copy
  1. void keyBoard::focusChanged(QWidget *, QWidget *nowWidget)  
  2. {  
  3.     if (nowWidget != 0 && !this->isAncestorOf(nowWidget))  
  4.     {  
  5.         if (nowWidget->inherits("QLineEdit"))  
  6.         {  
  7.             currentLineEdit = (QLineEdit *)nowWidget;  
  8.   
  9.             QPoint movePoint;  
  10.   
  11.             // 鼠标点击位置坐标  
  12.             if (QCursor::pos().y() > deskHeight / 2)  
  13.             {  
  14.                 // 靠上居中显示  
  15.                 movePoint = QPoint(deskWidth/2 - frmWidth/2, 0);  
  16.             }  
  17.             else  
  18.             {  
  19.                 // 靠下居中显示  
  20.                 movePoint = QPoint(deskWidth/2 - frmWidth/2, deskHeight - frmHeight);  
  21.             }  
  22.   
  23.             this->move(movePoint);  
  24.             this->repaint();  
  25.             this->setVisible(true);  
  26.         }  
  27.         else  
  28.         {  
  29.             currentLineEdit = 0;  
  30.             //qDebug() << "BBB";  
  31.             this->setVisible(false);  
  32.             // 需要将输入法切换到最初的原始状态--小写  
  33.             currentType="min";  
  34.             changeType(currentType);  
  35.             currentStyle = 0;  
  36.             changeStyle(currentStyle);  
  37.             keyWindow->setCurrentIndex(0);  
  38.         }  
  39.     }  
  40. }  
首先,判断当前焦点是否在QLineEdit控件中,然后根据焦点的坐标,显示键盘的位置。

5、按键处理函数
[plain] view plain copy
  1. void keyBoard::slotBtnClicked()  
  2. {  
  3.     QPushButton *btn = (QPushButton *)sender();  
  4.     QString objectName = btn->objectName();  
  5.   
  6.     if (objectName == "typeBtn")  
  7.     {  
  8.         if (currentType == "min")  
  9.         {  
  10.             currentType = "max";  
  11.         }  
  12.         else if (currentType == "max")  
  13.         {  
  14.             currentType = "sign";  
  15.         }  
  16.         else  
  17.         {  
  18.             currentType = "min";  
  19.         }  
  20.         changeType(currentType);  
  21.     }  
  22.     else if (objectName == "delBtn")  
  23.   
  24. 。。。。。。  
  25.   
  26.     else  
  27.     {  
  28.         QString value = btn->text();  
  29.         // 如果是&按钮,因为对应&被过滤,所以真实的text为去除前面一个&字符  
  30.         if (value == "&&")  
  31.         {  
  32.             value = value.right(1);  
  33.         }  
  34.         // 当前不是中文模式,则单击按钮对应text为传递参数  
  35.         if (currentType != "chinese")  
  36.         {  
  37.             if (currentLineEdit != 0)  
  38.             {  
  39.                 currentLineEdit->insert(value);  
  40.             }  
  41.         }  
  42.     }  
  43. }  
根据按键的objectName区分不同的按键,进行相应的处理。

6、主函数调用方法
[plain] view plain copy
  1. #include "keyBoard.h"  
  2.   
  3. int main(int argc, char *argv[])  
  4. {  
  5.     QApplication a(argc, argv);  
  6.     keyBoard keyBoard;  
  7.     keyBoard.hide();  
  8.   
  9.     MainWindow w;  
  10.     w.show();  
  11.   
  12.     return a.exec();  
  13. }  

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

四、效果





五、总结   

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


程序完整源码见附件。
http://download.csdn.net/download/wzs250969969/10050991

猜你喜欢

转载自blog.csdn.net/zx249388847/article/details/80523306