我买了一块Tontec 2.4英寸触摸屏(http://elinux.org/MZTX-PI-EXT)给我的树莓派。触摸屏控制器需要"tsc2007.ko"one_answers"tsp_raspi.ko"内核模块,如elinux文章中所述。tsc2007.ko模块在Raspbian内核树中,但tsp_raspi.ko可以在这里找到:https://github.com/osandov/raspi/tree/master/tsc2007.
我已经用这些模块交叉编译了一个新的Pi内核,它们加载良好,并在Raspbian中创建了一个/dev/input/event0设备。如果我"evtest"该设备并触摸屏幕,我会得到输出,这样我就知道事件是在Linux中传递的:
pi@raspberry /dev/input $ evtest
Available devices:
/dev/input/event0: TSC2007 Touchscreen
Select the device event number [0-0]: 0
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0
Input device name: "TSC2007 Touchscreen"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 330 (BTN_TOUCH)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 1922
Min 0
Max 4095
Fuzz 64
Event code 1 (ABS_Y)
Value 2221
Min 0
Max 4095
Fuzz 64
Event code 24 (ABS_PRESSURE)
Value 0
Min 0
Max 4095
Fuzz 64
Properties:
Testing ... (interrupt to exit)
Event: time 1425521704.199489, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1425521704.199489, type 3 (EV_ABS), code 1 (ABS_Y), value 2085
Event: time 1425521704.199489, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 538
Event: time 1425521704.199489, -------------- SYN_REPORT ------------
Event: time 1425521704.209174, type 3 (EV_ABS), code 0 (ABS_X), value 1455
...
我安装了tslib并运行了一个快速的ts_calibrate。我还确保ts_test在触摸屏幕时吐出数据。
为了在Qt5中支持tslib,我在/etc/profile中添加了以下环境变量:
## For Qt5 Touchscreen Support
export QT_DEBUG_PLUGINS=1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/arm-linux-gnueabihf/
export QT_PLUGIN_PATH=/usr/lib/plugins
export QT_QPA_FONTDIR=/usr/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/plugins/platforms
export QT_QPA_PLATFORM=linuxfb
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event0
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0
export TSLIB_TSEVENTTYPE='INPUT'
export TSLIB_CALIBFILE='/etc/pointercal'
export TSLIB_CONFFILE='/etc/ts.conf'
export TSLIB_CONSOLEDEVICE='none'
export TSLIB_FBDEVICE='/dev/fb0'
export TSLIB_PLUGINDIR='/usr/lib/ts'
export TSLIB_TSDEVICE='/dev/input/event0'
我阅读了Qt5文档以及如何在我的应用程序中获取触摸事件。我有一个主Widget,并在构造函数中设置适当的标志:
MainWidget::MainWidget(QLabel *parent)
: QLabel(parent)
{
qDebug() << "Setting WA_AcceptTouchEvents on MainWidget...";
// Accept touch events
setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_StaticContents);
}
我设置了一个事件过滤器,试图捕捉触摸事件:
bool MainWidget::eventFilter( QObject* target, QEvent* e )
{
qDebug() << "Event Type: " << e->type();
return false;
return QLabel::eventFilter(target, e);
}
我这样启动我的应用程序:
myapp-平台linuxfb:fb=/dev/fb0-插件tslib:/dev/input/event0
我还取消了qtslib.cpp:的Qt源代码中单个printf的注释
void QTsLibMouseHandler::readMouseData()
{
ts_sample sample;
while (get_sample(m_dev, &sample, m_rawMode)) {
bool pressed = sample.pressure;
int x = sample.x;
int y = sample.y;
// work around missing coordinates on mouse release
if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) {
x = m_x;
y = m_y;
}
if (!m_rawMode) {
//filtering: ignore movements of 2 pixels or less
int dx = x - m_x;
int dy = y - m_y;
if (dx*dx <= 4 && dy*dy <= 4 && pressed == m_pressed)
continue;
}
QPoint pos(x, y);
//printf("handleMouseEvent %d %d %d %ldn", m_x, m_y, pressed, sample.tv.tv_usec);
QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton);
m_x = x;
m_y = y;
m_pressed = pressed;
}
}
当我启动我的Qt应用程序时,我看到插件加载正常(甚至显示了正确的event0文件)。我还看到,当我触摸屏幕时,qt-tslib插件正在接收触摸事件。问题是从来没有调用过事件过滤器!
以下是正在启动的应用程序:
Got keys from plugin meta data ("tslib", "tslibraw")
QFactoryLoader::QFactoryLoader() checking directory path "/home/pi/generic" ...
loaded library "/usr/lib/qt/plugins/generic/libqtslibplugin.so"
QTsLibMouseHandler "tslib" ""
QTsLibMouseHandler "tslib" "/dev/input/event0"
QFactoryLoader::QFactoryLoader() checking directory path "/usr/lib/qt/plugins/styles" ...
QFactoryLoader::QFactoryLoader() checking directory path "/home/pi/styles" ...
Setting WA_AcceptTouchEvents on MainWidget...
-----------------------------------------
Waiting for data now...
-----------------------------------------
handleMouseEvent 0 0 1 751196
handleMouseEvent 0 0 1 751196
handleMouseEvent 1696 1615 1 771075
handleMouseEvent 1696 1615 1 771075
handleMouseEvent 1679 1622 1 781368
handleMouseEvent 1671 1638 1 781368
handleMouseEvent 1679 1622 1 781368
handleMouseEvent 1671 1638 1 781368
...
我发现一些论坛帖子中,人们在使用linuxfb平台插件进行触摸输入时遇到了问题:
http://comments.gmane.org/gmane.comp.lib.qt.user/5686
http://qt-project.org/forums/viewthread/35757
http://qt-project.org/forums/viewthread/36120/
我已经尝试了他们的所有建议,但仍然存在问题——我的应用程序没有收到任何触摸事件,尽管Qt-tslib插件说它正在接收这些事件。
似乎tslib插件在将它接收到的事件注入我的应用程序的事件循环时遇到了问题:
QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton);
我还尝试了Qt5.4触摸指纹示例,并看到了相同的行为-没有接收到触摸事件。
我不知道从这里到哪里去。如果能为我解决这个问题提供任何帮助,我将不胜感激。谢谢
更新:
我更改了事件过滤器,使其看起来像这样:
bool MainWidget::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "Event received" << obj->metaObject()->className() << event->type();
switch (event->type()) {
case QEvent::TouchBegin:
qDebug() << "TouchBegin";
case QEvent::TouchUpdate:
qDebug() << "TouchUpdate";
case QEvent::TouchEnd:
qDebug() << "TouchEnd";
{
// QTouchEvent *touch = static_cast<QTouchEvent *>(event);
// QList<QTouchEvent::TouchPoint> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
// foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) {
// switch (touchPoint.state()) {
// case Qt::TouchPointStationary:
// // don't do anything if this touch point hasn't moved
// continue;
// default:
// {
// }
// break;
// }
// }
// break;
}
//default:
//return QLabel::event(event);
}
//return true;
}
现在,每当我触摸屏幕时,我都可以看到"套接字通知程序"事件与Qt-Tslib插件的打印混合在一起。为什么事件类型为50但没有触摸事件,有什么想法吗?
Event received QSocketNotifier 50
handleMouseEvent 2702 2618 0 557715
Event received QSocketNotifier 50
handleMouseEvent 2698 2612 1 547758
Event received QSocketNotifier 50
handleMouseEvent 2706 2802 1 759928
Event received QSocketNotifier 50
Event received QSocketNotifier 50
更新#2:
我安装事件过滤器只是为了捕捉任何事件。我不确定在Qt5中是什么将事件类型50(QSocketNotificationer)转换为QTouch*或QMouse*事件。
以下是更多信息:
- 当我运行evtest时,我看到屏幕分辨率很大(~2500 x~2500),实际屏幕为320x240。我试着改变//boot/config.txt中的dev/fb0帧缓冲区大小为320x240,以及重新启动。但是evtest和ts_calibrate步骤仍然显示出决议
- 由于分辨率较大,我尝试制作我的主要小部件10000x10000,看看我是否会得到触摸或鼠标事件-但我仍然只获取QSocketNotifier
- 然后,我试图强制tslib插件始终在屏幕位置X=50 Y=50,但我仍然只得到事件类型50QSocketNotifier
通过确保tslib插件安装在RasbperryPi上,问题得到了解决。
TSLIB_PLUGINDIR=/usr/lib/ts
Pi上不存在目录/usr/lib/ts。