Painter Paths Example | Qt Widgets 5.13.0

Qt 5.13 | Qt Widgets | Painter Paths Example

Qt 5.13.0 Reference Documentation

# Painter Paths Example

      /****************************************************************************
      **
      ** Copyright (C) 2016 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, 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 "renderarea.h"
      #include "window.h"

      #include <QtWidgets>

      #include <qmath.h>

      Window::Window()
      {
          QPainterPath rectPath;
          rectPath.moveTo(20.0, 30.0);
          rectPath.lineTo(80.0, 30.0);
          rectPath.lineTo(80.0, 70.0);
          rectPath.lineTo(20.0, 70.0);
          rectPath.closeSubpath();

          QPainterPath roundRectPath;
          roundRectPath.moveTo(80.0, 35.0);
          roundRectPath.arcTo(70.0, 30.0, 10.0, 10.0, 0.0, 90.0);
          roundRectPath.lineTo(25.0, 30.0);
          roundRectPath.arcTo(20.0, 30.0, 10.0, 10.0, 90.0, 90.0);
          roundRectPath.lineTo(20.0, 65.0);
          roundRectPath.arcTo(20.0, 60.0, 10.0, 10.0, 180.0, 90.0);
          roundRectPath.lineTo(75.0, 70.0);
          roundRectPath.arcTo(70.0, 60.0, 10.0, 10.0, 270.0, 90.0);
          roundRectPath.closeSubpath();

          QPainterPath ellipsePath;
          ellipsePath.moveTo(80.0, 50.0);
          ellipsePath.arcTo(20.0, 30.0, 60.0, 40.0, 0.0, 360.0);

          QPainterPath piePath;
          piePath.moveTo(50.0, 50.0);
          piePath.arcTo(20.0, 30.0, 60.0, 40.0, 60.0, 240.0);
          piePath.closeSubpath();

          QPainterPath polygonPath;
          polygonPath.moveTo(10.0, 80.0);
          polygonPath.lineTo(20.0, 10.0);
          polygonPath.lineTo(80.0, 30.0);
          polygonPath.lineTo(90.0, 70.0);
          polygonPath.closeSubpath();

          QPainterPath groupPath;
          groupPath.moveTo(60.0, 40.0);
          groupPath.arcTo(20.0, 20.0, 40.0, 40.0, 0.0, 360.0);
          groupPath.moveTo(40.0, 40.0);
          groupPath.lineTo(40.0, 80.0);
          groupPath.lineTo(80.0, 80.0);
          groupPath.lineTo(80.0, 40.0);
          groupPath.closeSubpath();

          QPainterPath textPath;
          QFont timesFont("Times", 50);
          timesFont.setStyleStrategy(QFont::ForceOutline);
          textPath.addText(10, 70, timesFont, tr("Qt"));

          QPainterPath bezierPath;
          bezierPath.moveTo(20, 30);
          bezierPath.cubicTo(80, 0, 50, 50, 80, 80);

          QPainterPath starPath;
          starPath.moveTo(90, 50);
          for (int i = 1; i < 5; ++i) {
              starPath.lineTo(50 + 40 * std::cos(0.8 * i * M_PI),
                              50 + 40 * std::sin(0.8 * i * M_PI));
          }
          starPath.closeSubpath();

          renderAreas.push_back(new RenderArea(rectPath));
          renderAreas.push_back(new RenderArea(roundRectPath));
          renderAreas.push_back(new RenderArea(ellipsePath));
          renderAreas.push_back(new RenderArea(piePath));
          renderAreas.push_back(new RenderArea(polygonPath));
          renderAreas.push_back(new RenderArea(groupPath));
          renderAreas.push_back(new RenderArea(textPath));
          renderAreas.push_back(new RenderArea(bezierPath));
          renderAreas.push_back(new RenderArea(starPath));

          fillRuleComboBox = new QComboBox;
          fillRuleComboBox->addItem(tr("Odd Even"), Qt::OddEvenFill);
          fillRuleComboBox->addItem(tr("Winding"), Qt::WindingFill);

          fillRuleLabel = new QLabel(tr("Fill &Rule:"));
          fillRuleLabel->setBuddy(fillRuleComboBox);

          fillColor1ComboBox = new QComboBox;
          populateWithColors(fillColor1ComboBox);
          fillColor1ComboBox->setCurrentIndex(fillColor1ComboBox->findText("mediumslateblue"));

          fillColor2ComboBox = new QComboBox;
          populateWithColors(fillColor2ComboBox);
          fillColor2ComboBox->setCurrentIndex(fillColor2ComboBox->findText("cornsilk"));

          fillGradientLabel = new QLabel(tr("&Fill Gradient:"));
          fillGradientLabel->setBuddy(fillColor1ComboBox);

          fillToLabel = new QLabel(tr("to"));
          fillToLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

          penWidthSpinBox = new QSpinBox;
          penWidthSpinBox->setRange(0, 20);

          penWidthLabel = new QLabel(tr("&Pen Width:"));
          penWidthLabel->setBuddy(penWidthSpinBox);

          penColorComboBox = new QComboBox;
          populateWithColors(penColorComboBox);
          penColorComboBox->setCurrentIndex(penColorComboBox->findText("darkslateblue"));

          penColorLabel = new QLabel(tr("Pen &Color:"));
          penColorLabel->setBuddy(penColorComboBox);

          rotationAngleSpinBox = new QSpinBox;
          rotationAngleSpinBox->setRange(0, 359);
          rotationAngleSpinBox->setWrapping(true);
          rotationAngleSpinBox->setSuffix(QLatin1String("\xB0"));

          rotationAngleLabel = new QLabel(tr("&Rotation Angle:"));
          rotationAngleLabel->setBuddy(rotationAngleSpinBox);

          connect(fillRuleComboBox, QOverload<int>::of(&QComboBox::activated),
                  this, &Window::fillRuleChanged);
          connect(fillColor1ComboBox, QOverload<int>::of(&QComboBox::activated),
                  this, &Window::fillGradientChanged);
          connect(fillColor2ComboBox, QOverload<int>::of(&QComboBox::activated),
                  this, &Window::fillGradientChanged);
          connect(penColorComboBox, QOverload<int>::of(&QComboBox::activated),
                  this, &Window::penColorChanged);

          for (RenderArea *area : qAsConst(renderAreas)) {
              connect(penWidthSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
                      area, &RenderArea::setPenWidth);
              connect(rotationAngleSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
                      area, &RenderArea::setRotationAngle);
          }

          QGridLayout *topLayout = new QGridLayout;

          int i = 0;
          for (RenderArea *area : qAsConst(renderAreas)) {
              topLayout->addWidget(area, i / 3, i % 3);
              ++i;
          }

          QGridLayout *mainLayout = new QGridLayout;
          mainLayout->addLayout(topLayout, 0, 0, 1, 4);
          mainLayout->addWidget(fillRuleLabel, 1, 0);
          mainLayout->addWidget(fillRuleComboBox, 1, 1, 1, 3);
          mainLayout->addWidget(fillGradientLabel, 2, 0);
          mainLayout->addWidget(fillColor1ComboBox, 2, 1);
          mainLayout->addWidget(fillToLabel, 2, 2);
          mainLayout->addWidget(fillColor2ComboBox, 2, 3);
          mainLayout->addWidget(penWidthLabel, 3, 0);
          mainLayout->addWidget(penWidthSpinBox, 3, 1, 1, 3);
          mainLayout->addWidget(penColorLabel, 4, 0);
          mainLayout->addWidget(penColorComboBox, 4, 1, 1, 3);
          mainLayout->addWidget(rotationAngleLabel, 5, 0);
          mainLayout->addWidget(rotationAngleSpinBox, 5, 1, 1, 3);
          setLayout(mainLayout);

          fillRuleChanged();
          fillGradientChanged();
          penColorChanged();
          penWidthSpinBox->setValue(2);

          setWindowTitle(tr("Painter Paths"));
      }

      void Window::fillRuleChanged()
      {
          Qt::FillRule rule = (Qt::FillRule)currentItemData(fillRuleComboBox).toInt();

          for (RenderArea *area : qAsConst(renderAreas))
              area->setFillRule(rule);
      }

      void Window::fillGradientChanged()
      {
          QColor color1 = qvariant_cast<QColor>(currentItemData(fillColor1ComboBox));
          QColor color2 = qvariant_cast<QColor>(currentItemData(fillColor2ComboBox));

          for (RenderArea *area : qAsConst(renderAreas))
              area->setFillGradient(color1, color2);
      }

      void Window::penColorChanged()
      {
          QColor color = qvariant_cast<QColor>(currentItemData(penColorComboBox));

          for (RenderArea *area : qAsConst(renderAreas))
              area->setPenColor(color);
      }

      void Window::populateWithColors(QComboBox *comboBox)
      {
          const QStringList colorNames = QColor::colorNames();
          for (const QString &name : colorNames)
              comboBox->addItem(name, QColor(name));
      }

      QVariant Window::currentItemData(QComboBox *comboBox)
      {
          return comboBox->itemData(comboBox->currentIndex());
      }