-
-
Save oKcerG/b9527a638b01523c3c9c06647d373338 to your computer and use it in GitHub Desktop.
QML NotchedRectangle https://gfycat.com/fr/whichambitiousannelida
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QGuiApplication> | |
#include <QQmlApplicationEngine> | |
#include <QQuickStyle> | |
#include "notchedrectangle.h" | |
int main(int argc, char *argv[]) | |
{ | |
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); | |
QQuickStyle::setStyle("Material"); | |
qmlRegisterType<NotchedRectangle>("Test", 1, 0, "NotchedRectangle"); | |
QGuiApplication app(argc, argv); | |
QQmlApplicationEngine engine; | |
const QUrl url(QStringLiteral("qrc:/main.qml")); | |
engine.load(url); | |
return app.exec(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import QtQuick 2.14 | |
import QtQuick.Window 2.14 | |
import QtQuick.Controls 2.14 | |
import QtQuick.Controls.Material 2.14 | |
import Test 1.0 | |
Window { | |
id: window | |
visible: true | |
width: 640 | |
height: 480 | |
title: qsTr("Hello World") | |
Column { | |
Slider { | |
id: radiusSlider | |
to: 300 | |
value: 30 | |
} | |
Slider { | |
id: cornerRadiusSlider | |
to: 300 | |
value: 4 | |
} | |
Slider { | |
id: marginSlider | |
to: 50 | |
value: 8 | |
} | |
Slider { | |
id: ySlider | |
from: -50 | |
to: 50 | |
value: 0 | |
} | |
} | |
NotchedRectangle { | |
id: rect | |
anchors { | |
left: parent.left | |
right: parent.right | |
bottom: parent.bottom | |
} | |
property bool shown: true | |
height: shown ? parent.height / 2 : 0 | |
Behavior on height { | |
NumberAnimation { | |
easing.type: Easing.InOutQuad | |
duration: 500 | |
} | |
} | |
notchCenter: Qt.point(fab.x + fab.width / 2, fab.y + fab.height / 2) | |
notchRadius: (fab.width / 2 + marginSlider.value) * fab.scale | |
cornerRadius: cornerRadiusSlider.value * fab.scale | |
color: "#6200EE" | |
Component.onCompleted: print(color) | |
RoundButton { | |
id: fab | |
x: centerX - width / 2 | |
y: ySlider.value - height / 2 + rect.height - window.height / 2 | |
width: radiusSlider.value * 2 | |
height: width | |
Material.background: "black" | |
onClicked: rect.shown = !rect.shown | |
property double centerX: parent.width / 2 | |
Behavior on centerX { | |
SequentialAnimation { | |
PropertyAnimation { | |
target: fab | |
property: "scale" | |
to: 0 | |
easing.type: Easing.OutQuad | |
duration: 150 | |
} | |
PropertyAction {} | |
PropertyAnimation { | |
target: fab | |
property: "scale" | |
to: 1 | |
easing.type: Easing.OutQuad | |
duration: 150 | |
} | |
} | |
} | |
} | |
TapHandler { | |
onTapped: fab.centerX = point.position.x | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "notchedrectangle.h" | |
#include <QPainter> | |
#include <QPainterPath> | |
#include <QDebug> | |
#include <cmath> | |
NotchedRectangle::NotchedRectangle() | |
{ | |
setAntialiasing(true); | |
} | |
void NotchedRectangle::paint(QPainter* painter) | |
{ | |
QPainterPath path; | |
const double w = width(); | |
const double h = height(); | |
const double cx = m_notchCenter.x(); | |
const double cy = m_notchCenter.y(); | |
const double nr = m_notchRadius; | |
const double nd = m_notchRadius * 2; | |
const double cr = m_cornerRadius; | |
const double cd = cr * 2; | |
const double xDelta = std::sqrt(nr * nr + 2 * nr * cr - cy * cy + 2 * cy * cr); | |
const qreal angle = std::atan2(cr - cy, xDelta) * 180.0 / M_PI; | |
path.arcTo(cx - xDelta - cr, 0, cd, cd, 90, -90 + angle); | |
path.arcTo(cx - nr, cy - nr, nd, nd, -180 + angle, 180 - angle * 2); | |
path.arcTo(cx + xDelta - cr, 0, cd, cd, 180 - angle, -90 + angle); | |
path.lineTo(w, 0); | |
path.lineTo(w, h); | |
path.lineTo(path.currentPosition().x(), h); | |
path.lineTo(0, h); | |
painter->fillPath(path, m_color); | |
} | |
QColor NotchedRectangle::color() const | |
{ | |
return m_color; | |
} | |
void NotchedRectangle::setColor(QColor color) | |
{ | |
if (m_color == color) | |
return; | |
m_color = color; | |
emit colorChanged(); | |
} | |
double NotchedRectangle::notchRadius() const | |
{ | |
return m_notchRadius; | |
} | |
void NotchedRectangle::setNotchRadius(double notchRadius) | |
{ | |
if (qFuzzyCompare(m_notchRadius, notchRadius)) | |
return; | |
m_notchRadius = notchRadius; | |
emit notchRadiusChanged(); | |
update(); | |
} | |
QPointF NotchedRectangle::notchCenter() const | |
{ | |
return m_notchCenter; | |
} | |
void NotchedRectangle::setNotchCenter(QPointF notchCenter) | |
{ | |
if (m_notchCenter == notchCenter) | |
return; | |
m_notchCenter = notchCenter; | |
emit notchCenterChanged(); | |
update(); | |
} | |
double NotchedRectangle::cornerRadius() const | |
{ | |
return m_cornerRadius; | |
} | |
void NotchedRectangle::setCornerRadius(double cornerRadius) | |
{ | |
if (qFuzzyCompare(m_cornerRadius, cornerRadius)) | |
return; | |
m_cornerRadius = cornerRadius; | |
emit cornerRadiusChanged(); | |
update(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef NOTCHEDRECTANGLE_H | |
#define NOTCHEDRECTANGLE_H | |
#include <QQuickPaintedItem> | |
class NotchedRectangle : public QQuickPaintedItem | |
{ | |
Q_OBJECT | |
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) | |
Q_PROPERTY(QPointF notchCenter READ notchCenter WRITE setNotchCenter NOTIFY notchCenterChanged) | |
Q_PROPERTY(double notchRadius READ notchRadius WRITE setNotchRadius NOTIFY notchRadiusChanged) | |
Q_PROPERTY(double cornerRadius READ cornerRadius WRITE setCornerRadius NOTIFY cornerRadiusChanged) | |
public: | |
NotchedRectangle(); | |
void paint(QPainter* painter) override; | |
QColor color() const; | |
void setColor(QColor color); | |
QPointF notchCenter() const; | |
void setNotchCenter(QPointF notchCenter); | |
double notchRadius() const; | |
void setNotchRadius(double notchRadius); | |
double cornerRadius() const; | |
void setCornerRadius(double cornerRadius); | |
signals: | |
void colorChanged(); | |
void notchCenterChanged(); | |
void notchRadiusChanged(); | |
void cornerRadiusChanged(); | |
private: | |
QColor m_color; | |
QPointF m_notchCenter; | |
double m_notchRadius = 30; | |
double m_cornerRadius = 4; | |
}; | |
#endif // NOTCHEDRECTANGLE_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very nice. I came across this on https://forum.qt.io/topic/111454/qml-more-advanced-shapes and I will definitely bookmark this for some future use-case when I need to implement a custom QQuickPaintedItem.