一、开发环境
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
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