网上也有相同的文章,但在 QtCreator下不知道如何跟着网上的介绍来操作,所以写了此篇文章,照着做,保证有效 ^_^
创建Qt的键盘插件,重点是创建两个类:
一个基于QObject和QWSKeyboardHandler派生的 键盘处理类(Handler)
一个基于QKbdDriverPlugin派生的 键盘插件类(Plugin)
Handler类的主要作用是完成对底层键盘设备的打开、读取等操作,并将读取到的键值映射为Qt支持的键值。
Plugin类的主要作用是与外部接口(因为在一个动态链接库中,Plugin类是导出的),在该类中,去创建Handler类的对象。
OK,开始实施:
1. 创建一个动态库工程,并生成一个类,假设叫做:sbox4x4Handler,这个类就是我们的Handler类。
2. 实现Handler类。
修改sbox4x4handler.h,加入下面三个头文件:
#include <QObject>
#include <QtGui/QWSKeyboardHandler>
#include <QSocketNotifier>
将Sbox4x4修改成 QObject和QWSKeyboardHandler,并加入Q_OBJECT声明,
并在类中添加一个void kbdReadyRead()的slot函数,用于将来当键盘设备可读时读取键值:
class SBOX4X4SHARED_EXPORT Sbox4x4Handler
:public QObject, public QWSKeyboardHandler
{
Q_OBJECT
public:
Sbox4x4Handler(const QString &device = QString("/dev/kbd"), QObject *parent = 0);
~Sbox4x4Handler();
private:
int kbdFd;
QSocketNotifier *notifier;
private slots:
void kbdReadyRead();
};
其中,QSocketNotifier 用于对键盘设备文件进行状态检测,kbdFd用于保存键盘设备文件打开之后的描述符。
接下来,
修改sbox4x4handler.cpp文件,完成上述几个函数:
首先包含必要的头文件,如:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
在构造函数中,完成对设备的打开操作,并创建QSocketNotifier对象,永远检测设备的读状态:
Sbox4x4Handler::Sbox4x4Handler(const QString &device, QObject *parent)
:QObject(parent), QWSKeyboardHandler()
{
setObjectName("SAPP 4x4 Keyboard Handler");
this->kbdFd = ::open(device.toAscii().constData(), O_RDONLY);
if(this->kbdFd < 0)
return;
this->notifier = new QSocketNotifier(this->kbdFd, QSocketNotifier::Read, this);
connect(this->notifier, SIGNAL(activated(int)), this, SLOT(kbdReadyRead()));
}
析构函数中,关闭设备文件
Sbox4x4Handler::~Sbox4x4Handler()
{
if(this->kbdFd >= 0)
close(this->kbdFd);
}
在kbdReadyRead槽函数中,完成对设备文件的读取和键值映射:
void Sbox4x4Handler::kbdReadyRead()
{
char key;
// 读取设备文件
if(read(this->kbdFd, &key, sizeof(key)) != sizeof(key))
return;
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
// unicode用于保存映射之后的字符
int unicode = 0x0000;
// keycode用于保存映射之后的Qt::Key类型的键值
int keycode = 0;
switch(key)
{
case 0:
keycode = Qt::Key_0;
unicode = '0';
break;
case 1:
keycode = Qt::Key_1;
unicode = '1';
break;
case 2
keycode = Qt::Key_2;
unicode = '2';
break;
case 3:
keycode = Qt::Key_3;
unicode = '3';
break;
case 4:
keycode = Q:Key_4;
unicode = '4';
break;
case 5:
keycode = Qt::Key_5;
unicode = '5';
break;
case 6:
keycode = Qt::Key_6;
unicode = '6';
break;
case 7:
keycode = Qt::Key_7;
unicode = '7';
break;
case 8:
keycode = Qt::Key_8;
unicode = '8';
break;
case 9:
keycode = Qt::Key_9;
unicode = '9';
break;
case 10:
keycode = Qt::Key_A;
unicode = 'A';
break;
case 11:
keycode = Qt::Key_B;
unicode = 'B';
break;
case 12:
keycode = Qt::Key_C;
unicode = 'C';
break;
case 13:
keycode = Qt::Key_D;
unicode = 'D';
break;
case 14:
keycode = Qt::Key_E;
unicode = 'E';
break;
case 15:
keycode = Qt::Key_F;
unicode = 'F';
break;
default:
return;
}
this->processKeyEvent(unicode, keycode, modifiers, 1, false);
}
OK,QWSKeyboardHandler的派生类处理完毕。接下来,需要创建QKbdDriverPlugin的派生类。
首先创建一个新的C++ Class:
假设取名为Sbox4x4Plugin,Base Class输入QKbdDriverPlugin:
在Sbox4x4Plugin类中,重点是重载QKbdDriverPlugin基类中的create和keys:
注意,Qt Creator 自动生成的类定义中,包含的头文件不正确,直接包含QKbdDriverPlugin会提示找不到,需要加上QtGui/QKbdDriverPlugin
#include <QtGui/QKbdDriverPlugin>
class Sbox4x4Plugin : public QKbdDriverPlugin
{
Q_OBJECT
public:
Sbox4x4Plugin();
QWSKeyboardHandler *create(const QString &driverName, const QString &deviceName = QString("/dev/kbd"));
QStringList keys() const;
};
在sbox4x4plugin.cpp文件中,实现上述函数:
不要忘记包含sbox4x4handler.h头文件,因为在Plugin中,需要创建Sbox4x4Handler的类的对象。
#include "sbox4x4handler.h"
构造函数不需要做什么,保留为空
Sbox4x4Plugin::Sbox4x4Plugin()
{
}
在create中,重点是要创建一个自己的handler类对象,也就是sbox4x4的对象
QWSKeyboardHandler *Sbox4x4Plugin::create(const QString &driverName, const QString &deviceName)
{
if(driverName.toLower() == "sbox4x4")
return new Sbox4x4Handler(deviceName);
return NULL;
}
在keys函数中,返回插件的名字即可
QStringList Sbox4x4Plugin::keys() const
{
return QStringList() << "sbox4x4";
}
最后,不要忘记将sbox4x4这个库中的Plugin类导出
Q_EXPORT_PLUGIN2(sbox4x4, Sbox4x4Plugin);
OK,编译,大功告成。
使用:
使用方法很简单,
首先,将编译出的libsbox4x4.so复制到/usr/local/Trolltech/QtEmbedded-4.6.2-arm/plugins/kbddrivers目录下(没有目录则创建)
然后,增加一个QWS_KEYBOARD环境变量:
export QWS_KEYBOARD=sbox4x4:/dev/kbd
sbx4x4是库的名字,冒号后面是输入设备。
将来,sbox4x4和/dev/kbd将被传递到Sbox4x4Plugin的create函数中,用于创建键盘处理对象。
//----------------------------------------------------------------------
如下内容为自己根据实际使用时遇到的问题添加 by tumblerman
//----------------------------------------------------------------------
1.QT4.5.3内核中有一个现成的模板linuxis可以参考的,但4.7以后这个好像没4.5.3的好理解。
2.运行程序之前加 export QT_DEBUG_PLUGINS=1 可以看到插件载入过程中的错误。
3.export QWS_KEYBOARD=sbox4x4:/dev/kbd
sbox4x4(是库名libsbox4x4的后面部分,还是 _EXPORT_PLUGIN2(sbox4x4, Sbox4x4Plugin);中导出的名字?!没有深究过,参考(1)认为是前者,有兴趣的兄弟可以研究一下,但我的两个名字取的同一个,避免了这个问题)。
4.QT_PLUGIN_PATH要正确的设置。
参考资料:
(1).http://www.mculee.cn/post/93.html (转帖内容即是该文章)
(2).http://wenku.baidu.com/view/0a85cd83e53a580216fcfe9e.html
(3).http://blog.csdn.net/iskemin/archive/2009/12/21/5050448.aspx
(4).http://cuteqt.org/bbs/viewthread.php?tid=509&extra=&ordertype=1&sid=JsajfA&styleid=1