即使QTabletEvent被接受,QWidget的mousePressEvent也会被调用

mousePressEvent of QWidget gets called even though QTabletEvent was accepted

本文关键字:mousePressEvent 调用 QTabletEvent 即使 QWidget      更新时间:2023-10-16

在具有实现的tableEvent(QTabletEvent*事件)和mousePressEvent(QMouseEvent*事件。根据Qt文件,这种情况不应该发生:

事件处理程序QWidget::tableEvent()接收TabletPress、TabletRlease和TabletMove事件。Qt将首先发送一个平板电脑事件,然后如果任何小部件都不接受它,它将发送一个鼠标事件

主窗口.cpp

#include "mainwindow.h"
#include "tabletwidget.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    TabletWidget* tw = new TabletWidget(this);
    setCentralWidget(tw);
}

tabletwidget.h

#ifndef TABLETWIDGET_H
#define TABLETWIDGET_H
#include <QWidget>
class TabletWidget : public QWidget
{
    Q_OBJECT
public:
    explicit TabletWidget(QWidget *parent = 0);
protected:
    void tabletEvent(QTabletEvent *event) Q_DECL_OVERRIDE;
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
signals:
public slots:
};
#endif // TABLETWIDGET_H

桌面小工具.cpp

#include "tabletwidget.h"
#include <QDebug>
#include <QTabletEvent>
TabletWidget::TabletWidget(QWidget *parent) : QWidget(parent)
{
}
void TabletWidget::tabletEvent(QTabletEvent *event)
{
    event->accept();
    qDebug() << "tabletEvent: " << event->type();
}
void TabletWidget::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "mousePressEvent";
}

如果我使用笔尖或按下Wacom Intuos CTH-680S-DEIT的任何按钮,生成的输出为:

tabletEvent:  92
mousePressEvent
tabletEvent:  87
tabletEvent:  87
tabletEvent:  87
tabletEvent:  87
tabletEvent:  93

因此,首先调用tableEvent,即使我接受该事件,也会调用mousePressEvent。以下每个tableEvent的类型都是QTabletEvent::TabletMove,最后一个为QTabletEvent:TabletRlease。来自Qt文档:

QEvent::TabletMove 87
QEvent::TabletPress 92
QEvent::TabletRelease 93

我已经在Mac OS 10.10.3和Windows 7上测试过了,结果相同。这是个错误还是我做错了?

这在Qt 5.4.2中进行了测试。

事实上,根据Qt文档,在平板电脑使用时,Qt不应该发送鼠标事件。但它似乎无论如何都能做到(我使用的是5.5版本)

绕过它的一种方法是重新实现QApplicationevent()方法,即TabletEnterProximityTabletLeaveProximity的发送方法;则这些函数不被发送到CCD_ 5的CCD_。

因此,每当应用程序捕捉到TabletEnterProximityTabletLeaveProximity事件时,您都可以向TabletWidget发送一个信号来更改私有布尔变量_deviceActive。然后,在TabletWidget中,您为每个MousePressEvent(和MouseReleaseEvent)添加一个检查,以查看_deviceActive是否为真;并且仅当该标志为假时才实现该事件。

为了说明,继承的TabletApplication看起来是这样的:

class TabletApplication : public QApplication {
    Q_OBJECT
public:
    TabletApplication(int& argv, char** argc): QApplication(argv,argc){}
    bool event(QEvent* event){
        if (event->type() == QEvent::TabletEnterProximity || event->type() == QEvent::TabletLeaveProximity) {
            bool active = event->type() == QEvent::TabletEnterProximity? 1:0;
            emit sendTabletDevice(active);
            return true; 
        }
        return QApplication::event(event);
}
signals:
    void sendTabletActive(bool active);
};

以及tabletwidget.h:内部的附加部件

class TabletWidget : public QWidget {
// ...
public slots:
     void setTabletDeviceActive(bool active){
          _deviceActive = active;
     }
// ...
private:
     bool _deviceActive;
};

然后,如果设备处于活动状态,请检查鼠标内部的事件:

void TabletWidget::mousePressEvent(QMouseEvent *event)
{
     if (!_deviceActive) 
         qDebug() << "mousePressEvent";
}

当然,不要忘记将相应的信号与插槽连接起来。希望能有所帮助。

参考:TabletApplication from Qt tablet example