Turn the "concentriccircles" example into snippets, update screenshot
The example has a lot of code and documentation, but in essence shows how to use float-based QPainter APIs and how to set a render hint. That is two lines of code, which we can show as snippets. Update the screenshot of the example with a higher-resolution version. Fixes: QTBUG-119983 Change-Id: Iafcb813dff6ab8c269176f7994c95947ebf5e559 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> (cherry picked from commit 33254fb41f29b510d3d74dbaab60f0a67ef56d46) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 6c726979f744e85dc1284374ef1663a85647365e)
This commit is contained in:
parent
db1710d418
commit
f35eae4b79
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
@ -1,210 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\example painting/concentriccircles
|
||||
\title Concentric Circles Example
|
||||
\examplecategory {Graphics & Multimedia}
|
||||
\ingroup examples-painting
|
||||
\brief Demonstrates the improved quality that antialiasing and floating point precision gives.
|
||||
|
||||
\brief The Concentric Circles example shows the improved rendering
|
||||
quality that can be obtained using floating point precision and
|
||||
anti-aliasing when drawing custom widgets. The example also shows
|
||||
how to do simple animations.
|
||||
|
||||
The application's main window displays several widgets which are
|
||||
drawn using various combinations of precision and
|
||||
anti-aliasing.
|
||||
|
||||
\image concentriccircles-example.png
|
||||
|
||||
Anti-aliasing is one of QPainter's render hints. The
|
||||
QPainter::RenderHints are used to specify flags to QPainter that
|
||||
may, or may not, be respected by any given
|
||||
engine. QPainter::Antialiasing indicates that the engine should
|
||||
anti-alias the edges of primitives if possible, i.e. put
|
||||
additional pixels around the original ones to smooth the edges.
|
||||
|
||||
The difference between floating point precision and integer
|
||||
precision is a matter of accuracy, and is visible in the
|
||||
application's main window: Even though the logic that is
|
||||
calculating the circles' geometry is the same, floating points
|
||||
ensure that the white spaces between each circle are of the same
|
||||
size, while integers make two and two circles appear as if they
|
||||
belong together. The reason is that the integer based precision
|
||||
rely on rounding off non-integer calculations.
|
||||
|
||||
The example consists of two classes:
|
||||
|
||||
\list
|
||||
\li \c CircleWidget is a custom widget which renders several animated
|
||||
concentric circles.
|
||||
\li \c Window is the application's main window displaying four \c
|
||||
{CircleWidget}s drawn using different combinations of precision
|
||||
and aliasing.
|
||||
\endlist
|
||||
|
||||
First we will review the CircleWidget class, then we will take a
|
||||
look at the Window class.
|
||||
|
||||
\section1 CircleWidget Class Definition
|
||||
|
||||
The CircleWidget class inherits QWidget, and is a custom widget
|
||||
which renders several animated concentric circles.
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.h 0
|
||||
|
||||
We declare the \c floatBased and \c antialiased variables to hold
|
||||
whether an instance of the class should be rendered with integer
|
||||
or float based precision, and whether the rendering should be
|
||||
anti-aliased or not. We also declare functions setting each of
|
||||
these variables.
|
||||
|
||||
In addition we reimplement the QWidget::paintEvent() function to
|
||||
apply the various combinations of precision and anti-aliasing when
|
||||
rendering, and to support the animation. We reimplement the
|
||||
QWidget::minimumSizeHint() and QWidget::sizeHint() functions to
|
||||
give the widget a reasonable size within our application.
|
||||
|
||||
We declare the private \c nextAnimationFrame() slot, and the
|
||||
associated \c frameNo variable holding the number of "animation
|
||||
frames" for the widget, to facilitate the animation.
|
||||
|
||||
\section1 CircleWidget Class Implementation
|
||||
|
||||
In the constructor we make the widget's rendering integer based
|
||||
and aliased by default:
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 0
|
||||
|
||||
We initialize the widget's \c frameNo variable, and set the
|
||||
widget's background color using the QWidget::setBackgroundColor()
|
||||
function which takes a \l {QPalette::ColorRole}{color role} as
|
||||
argument; the QPalette::Base color role is typically white.
|
||||
|
||||
Then we set the widgets size policy using the
|
||||
QWidget::setSizePolicy() function. QSizePolicy::Expanding means
|
||||
that the widget's \l {QWidget::sizeHint()}{sizeHint()} is a
|
||||
sensible size, but that the widget can be shrunk and still be
|
||||
useful. The widget can also make use of extra space, so it should
|
||||
get as much space as possible.
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 1
|
||||
\codeline
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 2
|
||||
|
||||
The public \c setFloatBased() and \c setAntialiased() functions
|
||||
update the widget's rendering preferences, i.e. whether the widget
|
||||
should be rendered with integer or float based precision, and
|
||||
whether the rendering should be anti-aliased or not.
|
||||
|
||||
The functions also generate a paint event by calling the
|
||||
QWidget::update() function, forcing a repaint of the widget with
|
||||
the new rendering preferences.
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 3
|
||||
\codeline
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 4
|
||||
|
||||
The default implementations of the QWidget::minimumSizeHint() and
|
||||
QWidget::sizeHint() functions return invalid sizes if there is no
|
||||
layout for the widget, otherwise they return the layout's minimum and
|
||||
preferred size, respectively.
|
||||
|
||||
We reimplement the functions to give the widget minimum and
|
||||
preferred sizes which are reasonable within our application.
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 5
|
||||
|
||||
The nextAnimationFrame() slot simply increments the \c frameNo
|
||||
variable's value, and calls the QWidget::update() function which
|
||||
schedules a paint event for processing when Qt returns to the main
|
||||
event loop.
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 6
|
||||
|
||||
A paint event is a request to repaint all or part of the
|
||||
widget. The \c paintEvent() function is an event handler that can
|
||||
be reimplemented to receive the widget's paint events. We
|
||||
reimplement the event handler to apply the various combinations of
|
||||
precision and anti-aliasing when rendering the widget, and to
|
||||
support the animation.
|
||||
|
||||
First, we create a QPainter for the widget, and set its
|
||||
antialiased flag to the widget's preferred aliasing. We also
|
||||
translate the painters coordinate system, preparing to draw the
|
||||
widget's cocentric circles. The translation ensures that the
|
||||
center of the circles will be equivalent to the widget's center.
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 7
|
||||
|
||||
When painting a circle, we use the number of "animation frames" to
|
||||
determine the alpha channel of the circle's color. The alpha
|
||||
channel specifies the color's transparency effect, 0 represents a
|
||||
fully transparent color, while 255 represents a fully opaque
|
||||
color.
|
||||
|
||||
\snippet painting/concentriccircles/circlewidget.cpp 8
|
||||
|
||||
If the calculated alpha channel is fully transparent, we don't
|
||||
draw anything since that would be equivalent to drawing a white
|
||||
circle on a white background. Instead we skip to the next circle
|
||||
still creating a white space. If the calculated alpha channel is
|
||||
fully opaque, we set the pen (the QColor passed to the QPen
|
||||
constructor is converted into the required QBrush by default) and
|
||||
draw the circle. If the widget's preferred precision is float
|
||||
based, we specify the circle's bounding rectangle using QRectF and
|
||||
double values, otherwise we use QRect and integers.
|
||||
|
||||
The animation is controlled by the public \c nextAnimationFrame()
|
||||
slot: Whenever the \c nextAnimationFrame() slot is called the
|
||||
number of frames is incremented and a paint event is
|
||||
scheduled. Then, when the widget is repainted, the alpha-blending
|
||||
of the circles' colors change and the circles appear as animated.
|
||||
|
||||
\section1 Window Class Definition
|
||||
|
||||
The Window class inherits QWidget, and is the application's main
|
||||
window rendering four \c {CircleWidget}s using different
|
||||
combinations of precision and aliasing.
|
||||
|
||||
\snippet painting/concentriccircles/window.h 0
|
||||
|
||||
We declare the various components of the main window, i.e., the text
|
||||
labels and a double array that will hold reference to the four \c
|
||||
{CircleWidget}s. In addition we declare the private \c
|
||||
createLabel() function to simplify the constructor.
|
||||
|
||||
\section1 Window Class Implementation
|
||||
|
||||
\snippet painting/concentriccircles/window.cpp 0
|
||||
|
||||
In the constructor, we first create the various labels and put
|
||||
them in a QGridLayout.
|
||||
|
||||
\snippet painting/concentriccircles/window.cpp 1
|
||||
|
||||
Then we create a QTimer. The QTimer class is a high-level
|
||||
programming interface for timers, and provides repetitive and
|
||||
single-shot timers.
|
||||
|
||||
We create a timer to facilitate the animation of our concentric
|
||||
circles; when we create the four CircleWidget instances (and add
|
||||
them to the layout), we connect the QTimer::timeout() signal to
|
||||
each of the widgets' \c nextAnimationFrame() slots.
|
||||
|
||||
\snippet painting/concentriccircles/window.cpp 2
|
||||
|
||||
Before we set the layout and window title for our main window, we
|
||||
make the timer start with a timeout interval of 100 milliseconds,
|
||||
using the QTimer::start() function. That means that the
|
||||
QTimer::timeout() signal will be emitted, forcing a repaint of the
|
||||
four \c {CircleWidget}s, every 100 millisecond which is the reason
|
||||
the circles appear as animated.
|
||||
|
||||
\snippet painting/concentriccircles/window.cpp 3
|
||||
|
||||
The private \c createLabel() function is implemented to simlify
|
||||
the constructor.
|
||||
*/
|
@ -2,7 +2,6 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
qt_internal_add_example(basicdrawing)
|
||||
qt_internal_add_example(concentriccircles)
|
||||
qt_internal_add_example(affine)
|
||||
# qt_internal_add_example(composition) # FIXME: Seems buggy wrt. usesOpenGL function
|
||||
qt_internal_add_example(deform)
|
||||
|
@ -1,38 +0,0 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(concentriccircles LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/painting/concentriccircles")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(concentriccircles
|
||||
circlewidget.cpp circlewidget.h
|
||||
main.cpp
|
||||
window.cpp window.h
|
||||
)
|
||||
|
||||
set_target_properties(concentriccircles PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(concentriccircles PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS concentriccircles
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -1,84 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "circlewidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//! [0]
|
||||
CircleWidget::CircleWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
floatBased = false;
|
||||
antialiased = false;
|
||||
frameNo = 0;
|
||||
|
||||
setBackgroundRole(QPalette::Base);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
void CircleWidget::setFloatBased(bool floatBased)
|
||||
{
|
||||
this->floatBased = floatBased;
|
||||
update();
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
void CircleWidget::setAntialiased(bool antialiased)
|
||||
{
|
||||
this->antialiased = antialiased;
|
||||
update();
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
QSize CircleWidget::minimumSizeHint() const
|
||||
{
|
||||
return QSize(50, 50);
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
QSize CircleWidget::sizeHint() const
|
||||
{
|
||||
return QSize(180, 180);
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
void CircleWidget::nextAnimationFrame()
|
||||
{
|
||||
++frameNo;
|
||||
update();
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
void CircleWidget::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing, antialiased);
|
||||
painter.translate(width() / 2, height() / 2);
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
for (int diameter = 0; diameter < 256; diameter += 9) {
|
||||
int delta = abs((frameNo % 128) - diameter / 2);
|
||||
int alpha = 255 - (delta * delta) / 4 - diameter;
|
||||
//! [7] //! [8]
|
||||
if (alpha > 0) {
|
||||
painter.setPen(QPen(QColor(0, diameter / 2, 127, alpha), 3));
|
||||
|
||||
if (floatBased)
|
||||
painter.drawEllipse(QRectF(-diameter / 2.0, -diameter / 2.0, diameter, diameter));
|
||||
else
|
||||
painter.drawEllipse(QRect(-diameter / 2, -diameter / 2, diameter, diameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
//! [8]
|
@ -1,36 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef CIRCLEWIDGET_H
|
||||
#define CIRCLEWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
//! [0]
|
||||
class CircleWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CircleWidget(QWidget *parent = nullptr);
|
||||
|
||||
void setFloatBased(bool floatBased);
|
||||
void setAntialiased(bool antialiased);
|
||||
|
||||
QSize minimumSizeHint() const override;
|
||||
QSize sizeHint() const override;
|
||||
|
||||
public slots:
|
||||
void nextAnimationFrame();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
bool floatBased;
|
||||
bool antialiased;
|
||||
int frameNo;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // CIRCLEWIDGET_H
|
@ -1,11 +0,0 @@
|
||||
QT += widgets
|
||||
|
||||
HEADERS = circlewidget.h \
|
||||
window.h
|
||||
SOURCES = circlewidget.cpp \
|
||||
main.cpp \
|
||||
window.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/painting/concentriccircles
|
||||
INSTALLS += target
|
@ -1,14 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "window.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
Window window;
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "circlewidget.h"
|
||||
#include "window.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
//! [0]
|
||||
Window::Window()
|
||||
{
|
||||
aliasedLabel = createLabel(tr("Aliased"));
|
||||
antialiasedLabel = createLabel(tr("Antialiased"));
|
||||
intLabel = createLabel(tr("Int"));
|
||||
floatLabel = createLabel(tr("Float"));
|
||||
|
||||
QGridLayout *layout = new QGridLayout;
|
||||
layout->addWidget(aliasedLabel, 0, 1);
|
||||
layout->addWidget(antialiasedLabel, 0, 2);
|
||||
layout->addWidget(intLabel, 1, 0);
|
||||
layout->addWidget(floatLabel, 2, 0);
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
QTimer *timer = new QTimer(this);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
circleWidgets[i][j] = new CircleWidget;
|
||||
circleWidgets[i][j]->setAntialiased(j != 0);
|
||||
circleWidgets[i][j]->setFloatBased(i != 0);
|
||||
|
||||
connect(timer, &QTimer::timeout,
|
||||
circleWidgets[i][j], &CircleWidget::nextAnimationFrame);
|
||||
|
||||
layout->addWidget(circleWidgets[i][j], i + 1, j + 1);
|
||||
}
|
||||
}
|
||||
//! [1] //! [2]
|
||||
timer->start(100);
|
||||
setLayout(layout);
|
||||
|
||||
setWindowTitle(tr("Concentric Circles"));
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
QLabel *Window::createLabel(const QString &text)
|
||||
{
|
||||
QLabel *label = new QLabel(text);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
label->setMargin(2);
|
||||
label->setFrameStyle(QFrame::Box | QFrame::Sunken);
|
||||
return label;
|
||||
}
|
||||
//! [3]
|
@ -1,33 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
QT_END_NAMESPACE
|
||||
class CircleWidget;
|
||||
|
||||
//! [0]
|
||||
class Window : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window();
|
||||
|
||||
private:
|
||||
QLabel *createLabel(const QString &text);
|
||||
|
||||
QLabel *aliasedLabel;
|
||||
QLabel *antialiasedLabel;
|
||||
QLabel *intLabel;
|
||||
QLabel *floatLabel;
|
||||
CircleWidget *circleWidgets[2][2];
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // WINDOW_H
|
@ -1,6 +1,5 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = basicdrawing \
|
||||
concentriccircles \
|
||||
affine \
|
||||
composition \
|
||||
deform \
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 93 KiB |
@ -63,6 +63,7 @@ struct MyWidget : public QWidget
|
||||
void wrapper13();
|
||||
void wrapper14();
|
||||
void wrapper15();
|
||||
void concentricCircles();
|
||||
};
|
||||
QLine drawingCode;
|
||||
|
||||
@ -355,4 +356,21 @@ painter.drawRect(rectangle.adjusted(0, 0, -pen.width(), -pen.width()));
|
||||
|
||||
|
||||
} // MyWidget::wrapper15
|
||||
} // src_gui_painting_qpainter2
|
||||
|
||||
void MyWidget::concentricCircles()
|
||||
{
|
||||
//! [renderHint]
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
//! [renderHint]
|
||||
int diameter = 50;
|
||||
//! [floatBased]
|
||||
painter.drawEllipse(QRectF(-diameter / 2.0, -diameter / 2.0, diameter, diameter));
|
||||
//! [floatBased]
|
||||
//! [intBased]
|
||||
painter.drawEllipse(QRect(-diameter / 2, -diameter / 2, diameter, diameter));
|
||||
//! [intBased]
|
||||
|
||||
} // MyWidget::concentricCircles
|
||||
|
||||
} // src_gui_painting_qpainter2
|
@ -1125,24 +1125,22 @@ void QPainterPrivate::updateState(QPainterState *newState)
|
||||
The QPainter class also provides a means of controlling the
|
||||
rendering quality through its RenderHint enum and the support for
|
||||
floating point precision: All the functions for drawing primitives
|
||||
has a floating point version. These are often used in combination
|
||||
have floating point versions.
|
||||
|
||||
\snippet code/src_gui_painting_qpainter.cpp floatBased
|
||||
|
||||
These are often used in combination
|
||||
with the \l {RenderHint}{QPainter::Antialiasing} render hint.
|
||||
|
||||
\snippet code/src_gui_painting_qpainter.cpp renderHint
|
||||
|
||||
\table 100%
|
||||
\row
|
||||
\li Comparing concentric circles with int and float, and with or without
|
||||
anti-aliased rendering. Using the floating point precision versions
|
||||
produces evenly spaced rings. Anti-aliased rendering results in
|
||||
smooth circles.
|
||||
\li \inlineimage qpainter-concentriccircles.png
|
||||
\li
|
||||
\b {Concentric Circles Example}
|
||||
|
||||
The \l {painting/concentriccircles}{Concentric Circles} example
|
||||
shows the improved rendering quality that can be obtained using
|
||||
floating point precision and anti-aliasing when drawing custom
|
||||
widgets.
|
||||
|
||||
The application's main window displays several widgets which are
|
||||
drawn using the various combinations of precision and
|
||||
anti-aliasing.
|
||||
|
||||
\endtable
|
||||
|
||||
The RenderHint enum specifies flags to QPainter that may or may
|
||||
|
@ -63,7 +63,6 @@
|
||||
"painting/affine Example", "examples/widgets/painting/affine", "affine", 0, -1
|
||||
"painting/basicdrawing Example", "examples/widgets/painting/basicdrawing", "basicdrawing", 10, -1
|
||||
"painting/composition Example", "examples/widgets/painting/composition", "composition", 0, -1
|
||||
"painting/concentriccircles Example", "examples/widgets/painting/concentriccircles", "concentriccircles", 0, -1
|
||||
"painting/deform Example", "examples/widgets/painting/deform", "deform", 0, -1
|
||||
"painting/fontsampler Example", "examples/widgets/painting/fontsampler", "fontsampler", 0, -1
|
||||
"painting/gradients Example", "examples/widgets/painting/gradients", "gradients", 0, -1
|
||||
|
Loading…
x
Reference in New Issue
Block a user