將紅外遙控器製作成qt自定義鍵盤,
有兩種方法來處理qt自定義鍵盤。一種是直接編譯qt的源碼,另外一種是製作qt插件,通過加載插件來使用鍵盤。兩種方法各有不同,但實現的效果是一樣的。我使用的是插件法,因爲不需再編譯源碼,修改方便。
環境:ubuntu10.04+qtcreator2.5.2+QtEmbedded-4.5.3-arm
1、編寫紅外驅動
2、打開qtcreator2.5.2,創建一個動態庫工程,並生成一個類,庫名爲sbox4x4,類名爲sbox4x4Handler;
3、實現Handler類
修改sbox4x4handler.h,加入下面三個頭文件:
#include <QObject>
#include <QtGui/QWSKeyboardHandler>
#include <QSocketNotifier>
將Sbox4x4修改成 QObject和QWSKeyboardHandler,並加入Q_OBJECT聲明,並在類中添加一個void kbdReadyRead()的slot函數,用於將來當鍵盤設備可讀時讀取鍵值:
其中,QSocketNotifier 用於對鍵盤設備文件進行狀態檢測,kbdFd用於保存鍵盤設備文件打開之後的描述符。
#ifndef SBOX4X4HANDLER_H
#define SBOX4X4HANDLER_H
#include "sbox4x4_global.h"
#include <QObject>
#include <QtGui/QWSKeyboardHandler>
#include <QSocketNotifier>
class SBOX4X4SHARED_EXPORT sbox4x4Handler
:public QObject, public QWSKeyboardHandler
{
Q_OBJECT
public:
sbox4x4Handler(const QString &device = QString("/dev/ir"), QObject *parent = 0);
~sbox4x4Handler();
private:
int kbdFd;
QSocketNotifier *notifier;
private slots:
void kbdReadyRead();
};
#endif // SBOX4X4HANDLER_H
4、改sbox4x4handler.cpp文件,完成上述幾個函數:
#include "sbox4x4handler.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <QDebug>
//在構造函數中,完成對設備的打開操作,並創建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()
{
int key;
if(read(this->kbdFd, &key, sizeof(key)) < 0) // 讀取設備文件
return;
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
int unicode = 0x0000; //unicode 用於保存映射之後的字符
int keycode = 0; //keycode用於保存映射之後的Qt::Key類型的鍵值
switch(key)
{
case 0: keycode = Qt::Key_0; break; //可以選擇不同的鍵
case 1: keycode = Qt::Key_1; break;
case 2: keycode = Qt::Key_2; break;
case 3: keycode = Qt::Key_3; break;
case 4: keycode = Qt::Key_4; break;
case 5: keycode = Qt::Key_5; break;
case 6: keycode = Qt::Key_6; break;
case 7: keycode = Qt::Key_7; break;
case 8: keycode = Qt::Key_8; break;
case 9: keycode = Qt::Key_9; break;
case 10: keycode = Qt::Key_Up; break;
case 11: keycode = Qt::Key_Down; break;
case 12: keycode = Qt::Key_Left; break;
case 13: keycode = Qt::Key_Right; break;
case 14: keycode = Qt::Key_Enter; break;
case 15: keycode = Qt::Key_Direction_L; break;
case 16: keycode = Qt::Key_Tab; break;
case 17: keycode = Qt::Key_VolumeDown; break;
case 18: keycode = Qt::Key_VolumeUp; break;
case 19: keycode = Qt::Key_Backspace; break;
default:return;
}
this->processKeyEvent(unicode, keycode, modifiers, 1, false);
}
5、QKbdDriverPlugin的派生類。
首先創建一個新的C++ Class:
取名爲Sbox4x4Plugin,Base Class輸入QKbdDriverPlugin:
在Sbox4x4Plugin類中,重點是重載QKbdDriverPlugin基類中的create和keys:
注意,Qt Creator自動生成的類定義中,包含的頭文件不正確,直接包含QKbdDriverPlugin會提示找不到,需要加上QtGui/QKbdDriverPlugin
#include <QtGui/QKbdDriverPlugin>
#ifndef SBOX4X4PLUGIN_H
#define SBOX4X4PLUGIN_H
//#include <QKbdDriverPlugin>
#include <QtGui/QKbdDriverPlugin>
class Sbox4x4Plugin : public QKbdDriverPlugin
{
Q_OBJECT
public:
Sbox4x4Plugin();
QWSKeyboardHandler *create(const QString &driverName, const QString &deviceName = QString("/dev/ir"));
QStringList keys() const;
};
#endif // SBOX4X4PLUGIN_H
6、.在sbox4x4plugin.cpp文件中,實現上述函數:
包含sbox4x4handler.h頭文件,因爲在Plugin中,需要創建Sbox4x4Handler的類的對象。
#include "sbox4x4plugin.h"
#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";
}
Q_EXPORT_PLUGIN2(sbox4x4, Sbox4x4Plugin); //將sbox4x4這個庫中的Plugin類導出
7、編譯
需要注意的是,在文件的最後有Q_EXPORT_PLUGIN2 (sbox4x4,Sbox4x4Plugin)一句,這個宏的第一個參數是目標庫名字去除前綴lib和版本號及擴展名之後的基本名,這個基本名要和.pro指定的TARGET項保持一致,並且和環境變量的driver內容一致;第二個參數是插件的類名。我們使用宏Q_EXPORT_PLUGIN2,輸出插件,讓插件變得可以被QT使用。
8、使用
使用方法:首先,將編譯出的libsbox4x4.so複製到qt安裝目錄下的plugins/kbddrivers/(沒有目錄則創建)然後,增加一個QWS_KEYBOARD環境變量:
export QWS_KEYBOARD=sbox4x4:/dev/ir ,bx4x4是庫的名字,冒號後面是輸入設備。將來,sbox4x4和/dev/kbd將被傳遞到Sbox4x4Plugin的create函數中,用於創建鍵盤處理對象。然後qt自定義的鍵盤就可以用了。