Skip to content

Instantly share code, notes, and snippets.

@oKcerG

oKcerG/main.cpp Secret

Last active May 17, 2023 12:49
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save oKcerG/b9527a638b01523c3c9c06647d373338 to your computer and use it in GitHub Desktop.
Save oKcerG/b9527a638b01523c3c9c06647d373338 to your computer and use it in GitHub Desktop.
#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();
}
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
}
}
}
#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();
}
#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
@pestophagous
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment