5
votes

In a QWidget derived class object with implemented tabletEvent(QTabletEvent *event) and mousePressEvent(QMouseEvent *event), the mousePressEvent gets called every time tabletEvent gets called with type TabletEvent::TabletPress. According to the Qt documentation, this should not happen:

The event handler QWidget::tabletEvent() receives TabletPress, TabletRelease and TabletMove events. Qt will first send a tablet event, then if it is not accepted by any widget, it will send a mouse event.

mainwindow.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

tabletwidget.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";
}

The output generated if I use the tip of the pen or press any button of the Wacom Intuos CTH-680S-DEIT is:

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

So first the tabletEvent gets called, and even though I accept the event, mousePressEvent gets called anyway. Every following tabletEvent is of type QTabletEvent::TabletMove and the last one is QTabletEvent::TabletRelease. From the Qt documentation:

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

I have tested this on Mac OS 10.10.3 and Windows 7 with the same result. Is this a bug or am I doing it wrong?

This is tested on Qt 5.4.2.

1
Looks like a bug. For your testcase, you really should have the widget as a top-level window instead of putting it in the mainwindow - perhaps that's where the bugs originate from (unlikely but still - minimization is essential).Kuba hasn't forgotten Monica

1 Answers

4
votes

Indeed, according to Qt documentation, the Qt should not be sending mouse events when the tablet is in use. But it seems to do it anyway (I'm using version 5.5).

One way to get around it is to reimplement event() method of QApplication - that's where TabletEnterProximity and TabletLeaveProximity are sent; those functions are not sent to the QWidget's event().

So, whenever the application catches either TabletEnterProximity or TabletLeaveProximity events, you may send a signal to your TabletWidget to change a private bool variable _deviceActive. Then, inside the TabletWidget you add a check for each MousePressEvent (and MouseReleaseEvent) to see if the _deviceActive is true or not; and implement the event only if the flag is false.

To illustrate, the inherited TabletApplication would look like this:

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);
};

And the additional parts inside tabletwidget.h:

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

Then you check inside the mouse events if the device is active:

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

Of course, don't forget to connect the corresponding signal with the slot. Hope it helps.

Reference: TabletApplication from Qt tablet example