3

I was trying to handle QTabletEvent events generated from a WACOM Intuos ART tablet.

I succeeded with the following code but was obliged to resize my QWidget handling the tablet events to the full Windows desktop size in order to receive the tablet events from all its surface (whereever the pen is located). It seems by default the tablet surface is mapped to the full desktop. I want to map it to my own widget client area.

How to do this ?

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class TabletSampleWindow(QWidget):
    def __init__(self, parent=None):
        super(TabletSampleWindow, self).__init__(parent)
        self.pen_is_down = False
        self.pen_x = 0
        self.pen_y = 0
        self.pen_pressure = 0
        self.text = ""
        # Resizing the sample window to full desktop size:
        frame_rect = app.desktop().frameGeometry()
        width, height = frame_rect.width(), frame_rect.height()
        self.resize(width, height)
        self.move(-9, 0)
        self.setWindowTitle("Sample Tablet Event Handling")

    def tabletEvent(self, tabletEvent):
        self.pen_x = tabletEvent.globalX()
        self.pen_y = tabletEvent.globalY()
        self.pen_pressure = int(tabletEvent.pressure() * 100)
        if tabletEvent.type() == QTabletEvent.TabletPress:
            self.pen_is_down = True
            self.text = "TabletPress event"
        elif tabletEvent.type() == QTabletEvent.TabletMove:
            self.pen_is_down = True
            self.text = "TabletMove event"
        elif tabletEvent.type() == QTabletEvent.TabletRelease:
            self.pen_is_down = False
            self.text = "TabletRelease event"
        self.text += " at x={0}, y={1}, pressure={2}%,".format(self.pen_x, self.pen_y, self.pen_pressure)
        if self.pen_is_down:
            self.text += " Pen is down."
        else:
            self.text += " Pen is up."
        tabletEvent.accept()
        self.update()

    def paintEvent(self, event):
        text = self.text
        i = text.find("\n\n")
        if i >= 0:
            text = text.left(i)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.TextAntialiasing)
        painter.drawText(self.rect(), Qt.AlignTop | Qt.AlignLeft , text)

app = QApplication(sys.argv)
mainform = TabletSampleWindow()
mainform.show()
app.exec_()
Bug Raptor
  • 261
  • 6
  • 15
  • If it's mapped to the whole desktop does it also behave as a mouse would? (e.g. does clicking outside a small Qt widget change window focus?) – three_pineapples Mar 10 '18 at 13:06
  • Yes, absolutely. Clicking outside the QWidget (if not full desktop extended) will be interpreted as mouse events (since no widget will accept the QTabletEvent events mouse events will be generated). I don't want this behavior. I just want my widget to grab/capture the full tablet and map the tablet surface to my Widget client area. But I found no way to do this. – Bug Raptor Mar 10 '18 at 13:19
  • I suspect then the only way to do what you want (as far as I can see) is to A) stop the OS from responding to the tablet as a mouse and B) then use a 3rd party library to interface directly with the tablet and use that to generate Qt events manually with coordinates scaled depending on the window size fraction with respect to the desktop size. I'm honestly not sure how practical this suggestion is though. – three_pineapples Mar 10 '18 at 22:27
  • I’m wondering if I could try to create a whole desktop sized invisible QWidget handling and accepting all QTabletEvent events and signaling resized QTabletEvent events to its visible child widget displaying the drawing in its client area... But it’s a bit tricky, isn’t it ? Apparently the philosophy of a tablet is to be used as a mouse mapped to the whole desktop when clicking outside the drawing widget... My first intention appears to be out of this « philosophy »... – Bug Raptor Mar 11 '18 at 09:52

0 Answers0