- Qt 5.5
- Qt Widgets
- Tablet Example
- tabletcanvas.cpp Example File
- Qt 5.5.1 Reference Documentation

# tabletcanvas.cpp Example File

widgets/tablet/tabletcanvas.cpp

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** You may use this file under the terms of the BSD license as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    **   * Redistributions of source code must retain the above copyright
    **     notice, this list of conditions and the following disclaimer.
    **   * Redistributions in binary form must reproduce the above copyright
    **     notice, this list of conditions and the following disclaimer in
    **     the documentation and/or other materials provided with the
    **     distribution.
    **   * Neither the name of The Qt Company Ltd nor the names of its
    **     contributors may be used to endorse or promote products derived
    **     from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/

    #include <QtWidgets>
    #include <math.h>

    #include "tabletcanvas.h"

    TabletCanvas::TabletCanvas()
    {
        resize(500, 500);
        myBrush = QBrush();
        myPen = QPen();
        initPixmap();
        setAutoFillBackground(true);
        deviceDown = false;
        myColor = Qt::red;
        myTabletDevice = QTabletEvent::Stylus;
        alphaChannelType = NoAlpha;
        colorSaturationType = NoSaturation;
        lineWidthType = LineWidthPressure;
    }

    void TabletCanvas::initPixmap()
    {
        QPixmap newPixmap = QPixmap(width(), height());
        newPixmap.fill(Qt::white);
        QPainter painter(&newPixmap);
        if (!pixmap.isNull())
            painter.drawPixmap(0, 0, pixmap);
        painter.end();
        pixmap = newPixmap;
    }

    bool TabletCanvas::saveImage(const QString &file)
    {
        return pixmap.save(file);
    }

    bool TabletCanvas::loadImage(const QString &file)
    {
        bool success = pixmap.load(file);

        if (success) {
            update();
            return true;
        }
        return false;
    }

    void TabletCanvas::tabletEvent(QTabletEvent *event)
    {

        switch (event->type()) {
            case QEvent::TabletPress:
                if (!deviceDown) {
                    deviceDown = true;
                    polyLine[0] = polyLine[1] = polyLine[2] = event->pos();
                }
                break;
            case QEvent::TabletRelease:
                if (deviceDown)
                    deviceDown = false;
                break;
            case QEvent::TabletMove:
                polyLine[2] = polyLine[1];
                polyLine[1] = polyLine[0];
                polyLine[0] = event->pos();

                if (deviceDown) {
                    updateBrush(event);
                    QPainter painter(&pixmap);
                    paintPixmap(painter, event);
                }
                break;
            default:
                break;
        }
        update();
    }

    void TabletCanvas::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        painter.drawPixmap(0, 0, pixmap);
    }

    void TabletCanvas::paintPixmap(QPainter &painter, QTabletEvent *event)
    {
        QPoint brushAdjust(10, 10);

        switch (myTabletDevice) {
            case QTabletEvent::Airbrush:
                myBrush.setColor(myColor);
                myBrush.setStyle(brushPattern(event->pressure()));
                painter.setPen(Qt::NoPen);
                painter.setBrush(myBrush);

                for (int i = 0; i < 3; ++i) {
                    painter.drawEllipse(QRect(polyLine[i] - brushAdjust,
                                        polyLine[i] + brushAdjust));
                }
                break;
            case QTabletEvent::Puck:
            case QTabletEvent::FourDMouse:
            case QTabletEvent::RotationStylus:
                {
                    const QString error(tr("This input device is not supported by the example."));
    #ifndef QT_NO_STATUSTIP
                    QStatusTipEvent status(error);
                    QApplication::sendEvent(this, &status);
    #else
                    qWarning() << error;
    #endif
                }
                break;
            default:
                {
                    const QString error(tr("Unknown tablet device - treating as stylus"));
    #ifndef QT_NO_STATUSTIP
                    QStatusTipEvent status(error);
                    QApplication::sendEvent(this, &status);
    #else
                    qWarning() << error;
    #endif
                }
                // FALL-THROUGH
            case QTabletEvent::Stylus:
                painter.setBrush(myBrush);
                painter.setPen(myPen);
                painter.drawLine(polyLine[1], event->pos());
                break;
        }
    }

    Qt::BrushStyle TabletCanvas::brushPattern(qreal value)
    {
        int pattern = int((value) * 100.0) % 7;

        switch (pattern) {
            case 0:
                return Qt::SolidPattern;
            case 1:
                return Qt::Dense1Pattern;
            case 2:
                return Qt::Dense2Pattern;
            case 3:
                return Qt::Dense3Pattern;
            case 4:
                return Qt::Dense4Pattern;
            case 5:
                return Qt::Dense5Pattern;
            case 6:
                return Qt::Dense6Pattern;
            default:
                return Qt::Dense7Pattern;
        }
    }

    void TabletCanvas::updateBrush(QTabletEvent *event)
    {
        int hue, saturation, value, alpha;
        myColor.getHsv(&hue, &saturation, &value, &alpha);

        int vValue = int(((event->yTilt() + 60.0) / 120.0) * 255);
        int hValue = int(((event->xTilt() + 60.0) / 120.0) * 255);

        switch (alphaChannelType) {
            case AlphaPressure:
                myColor.setAlpha(int(event->pressure() * 255.0));
                break;
            case AlphaTilt:
                myColor.setAlpha(maximum(abs(vValue - 127), abs(hValue - 127)));
                break;
            default:
                myColor.setAlpha(255);
        }

        switch (colorSaturationType) {
            case SaturationVTilt:
                myColor.setHsv(hue, vValue, value, alpha);
                break;
            case SaturationHTilt:
                myColor.setHsv(hue, hValue, value, alpha);
                break;
            case SaturationPressure:
                myColor.setHsv(hue, int(event->pressure() * 255.0), value, alpha);
                break;
            default:
                ;
        }

        switch (lineWidthType) {
            case LineWidthPressure:
                myPen.setWidthF(event->pressure() * 10 + 1);
                break;
            case LineWidthTilt:
                myPen.setWidthF(maximum(abs(vValue - 127), abs(hValue - 127)) / 12);
                break;
            default:
                myPen.setWidthF(1);
        }

        if (event->pointerType() == QTabletEvent::Eraser) {
            myBrush.setColor(Qt::white);
            myPen.setColor(Qt::white);
            myPen.setWidthF(event->pressure() * 10 + 1);
        } else {
            myBrush.setColor(myColor);
            myPen.setColor(myColor);
        }
    }

    void TabletCanvas::resizeEvent(QResizeEvent *)
    {
        initPixmap();
        polyLine[0] = polyLine[1] = polyLine[2] = QPoint();
    }