Assign styles to rectangles (Make banner, polygon)
-
@aktay You'll need a custom control for this. The standard Rectangle can't be styled like that.
There are lots of good examples, tutorials, and books on extending Qml. Here is an online/free one https://qmlbook.github.io. It doesn't have a chapter on doing custom controls I don't think but it's worth a read. Maybe chapter 16 might cover it. Either way, you can find other tutorials and examples with a google search.
-
Hi! Easiest way to get custom shapes is by deriving from
QQuickPaintedItem
. See the following example with two custom items:myitem.h
#ifndef MYITEM_H #define MYITEM_H #include <QQuickPaintedItem> class MyItem : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged) Q_PROPERTY(QColor borderColor MEMBER m_borderColor NOTIFY borderColorChanged) Q_PROPERTY(qreal radius MEMBER m_radius NOTIFY radiusChanged) Q_PROPERTY(qreal borderWidth MEMBER m_borderWidth NOTIFY borderWidthChanged) public: MyItem(QQuickItem *parent = nullptr); virtual void paint(QPainter *painter) override; signals: void colorChanged(const QColor&); void borderColorChanged(const QColor&); void radiusChanged(qreal); void borderWidthChanged(qreal); private: QColor m_color{255,255,255}; QColor m_borderColor{0,0,0}; qreal m_radius{0.0}; qreal m_borderWidth{1.0}; }; #endif // MYITEM_H
myitem.cpp
#include "myitem.h" #include <QPainter> #include <QPen> #include <QBrush> #include <QColor> #include <QPointF> #include <QPainterPath> #include <QRectF> MyItem::MyItem(QQuickItem *parent) : QQuickPaintedItem(parent) { connect(this, SIGNAL(colorChanged(QColor)), this, SLOT(update())); connect(this, SIGNAL(borderColorChanged(QColor)), this, SLOT(update())); connect(this, SIGNAL(radiusChanged(qreal)), this, SLOT(update())); connect(this, SIGNAL(borderWidthChanged(qreal)), this, SLOT(update())); } void MyItem::paint(QPainter *painter) { painter->setRenderHint(QPainter::Antialiasing); const qreal w = width(); const qreal h = height(); const qreal p = m_borderWidth < 0.0 ? 0.0 : m_borderWidth; const qreal d = p/2.0; QPainterPath path; if (m_radius < 0.01) { path.moveTo(w-d,d); path.lineTo(d,d); path.lineTo(d,h-d); path.lineTo(w-d,h-d); path.lineTo(w-d,d); } else { path.moveTo(w-m_radius-d, d); path.arcTo(QRectF(QPointF(-m_radius+d,-m_radius+d),QPointF(m_radius+d,m_radius+d)), 0.0, -90.0); path.arcTo(QRectF(QPointF(-m_radius+d,h-m_radius-d),QPointF(m_radius+d,h+m_radius-d)), 90.0, -90.0); path.arcTo(QRectF(QPointF(w-m_radius-d,h-m_radius-d),QPointF(w+m_radius-d,h+m_radius-d)), 180.0, -90.0); path.arcTo(QRectF(QPointF(w-m_radius-d,-m_radius+d),QPointF(w+m_radius-d,m_radius+d)), 270.0, -90.0); } QPen pen; pen.setColor(m_borderColor); if (p > 0) { pen.setWidth(p); } else { pen.setStyle(Qt::NoPen); } painter->setPen(pen); QBrush brush; brush.setColor(m_color); brush.setStyle(Qt::SolidPattern); painter->setBrush(brush); painter->drawPath(path); }
mybanner.h
#ifndef MYBANNER_H #define MYBANNER_H #include <QQuickPaintedItem> class MyBanner : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged) Q_PROPERTY(QColor borderColor MEMBER m_borderColor NOTIFY borderColorChanged) Q_PROPERTY(qreal length MEMBER m_length NOTIFY lengthChanged) Q_PROPERTY(qreal borderWidth MEMBER m_borderWidth NOTIFY borderWidthChanged) public: MyBanner(QQuickItem *parent = nullptr); virtual void paint(QPainter *painter) override; signals: void colorChanged(const QColor&); void borderColorChanged(const QColor&); void lengthChanged(qreal); void borderWidthChanged(qreal); private: QColor m_color{255,255,255}; QColor m_borderColor{0,0,0}; qreal m_length{0.0}; qreal m_borderWidth{1.0}; }; #endif // MYBANNER_H
mybanner.cpp
#include "mybanner.h" #include <QPainter> #include <QPen> #include <QBrush> #include <QColor> #include <QPointF> #include <QPainterPath> #include <QRectF> MyBanner::MyBanner(QQuickItem *parent) : QQuickPaintedItem(parent) { connect(this, SIGNAL(colorChanged(QColor)), this, SLOT(update())); connect(this, SIGNAL(borderColorChanged(QColor)), this, SLOT(update())); connect(this, SIGNAL(lengthChanged(qreal)), this, SLOT(update())); connect(this, SIGNAL(borderWidthChanged(qreal)), this, SLOT(update())); } void MyBanner::paint(QPainter *painter) { painter->setRenderHint(QPainter::Antialiasing); const qreal w = width(); const qreal h = height(); const qreal p = m_borderWidth < 0.0 ? 0.0 : m_borderWidth; const qreal d = p/2.0; const qreal len = m_length > w ? w : m_length; QPainterPath path; path.moveTo(w-d,d); path.lineTo(d,d); path.lineTo(d,h-d); path.lineTo(w-d,h-d); path.lineTo(w-d-len,h/2.0); path.lineTo(w-d,d); QPen pen; pen.setColor(m_borderColor); if (p > 0) { pen.setWidth(p); } else { pen.setStyle(Qt::NoPen); } painter->setPen(pen); QBrush brush; brush.setColor(m_color); brush.setStyle(Qt::SolidPattern); painter->setBrush(brush); painter->drawPath(path); }
main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "myitem.h" #include "mybanner.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterType<MyItem>("io.qt.forum", 1, 0, "MyItem"); qmlRegisterType<MyBanner>("io.qt.forum", 1, 0, "MyBanner"); QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); }
main.qml
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import io.qt.forum 1.0 ApplicationWindow { visible: true width: 640 height: 480 color: "#d8d8d8" Row { x: 20 y: 20 spacing: 20 Column { spacing: -20 MyItem { width: 160; height: 60; radius: 12; color: "red"; } MyItem { width: 160; height: 60; radius: 12; color: "orange"; } MyItem { width: 160; height: 60; radius: 12; color: "yellow"; } MyItem { width: 160; height: 60; radius: 12; color: "lime"; } MyItem { width: 160; height: 60; radius: 12; color: "aqua"; } MyItem { width: 160; height: 60; radius: 12; color: "skyblue"; } } Column { spacing: -20 MyItem { width: 160; height: 60; radius: 12; color: "mediumorchid"; } MyItem { width: 160; height: 60; radius: 12; color: "thistle"; } MyItem { width: 160; height: 60; radius: 12; color: "hotpink"; } MyItem { width: 160; height: 60; radius: 12; color: "mistyrose"; } MyItem { width: 160; height: 60; radius: 12; color: "palegreen"; } MyItem { width: 160; height: 60; radius: 12; color: "paleturquoise"; } } Column { spacing: -20 MyItem { width: 160; height: 60; radius: 12; color: "saddlebrown"; } MyItem { width: 160; height: 60; radius: 12; color: "burlywood"; } MyItem { width: 160; height: 60; radius: 12; color: "black"; } MyItem { width: 160; height: 60; radius: 12; color: "darkgrey"; } MyItem { width: 160; height: 60; radius: 12; color: "lightgrey"; } MyItem { width: 160; height: 60; radius: 12; color: "white"; } } } MyBanner { x: 20 y: 400 width: 400 height: 60 length: 30 borderWidth: 2 color: "#a0a0a0" Text { anchors.centerIn: parent color: "white" text: "DIGITAL BANNERS" font.pixelSize: 30 font.family: "Liberation Serif" } } Rectangle { width: 300 height: 40 x: 50 y: 320 rotation: -5 antialiasing: true Text { font.pixelSize: 24 anchors.centerIn: parent text: "<font face='verdana' color='red'>forum</font>.<font face='Courier' color='green'>Qt</font>.<b>io</b>" } } }
-
@Wieland
Thank you for your effort.But to draw this picture. And in this way, objects can not be buried in shapes. I think I will solve my problem with png pictures. I will make some parts of the pictures transparent and some of them black background.
Then, z: -1 and z: 1 values will appear in the transparent area where I want them to appear, the areas I want to hide will stay under the black background.
For example:
Image{ id:backgroundImage source: "background.png" Map{ id :map ancohrs.fill:parent anchors.centerIn:parent.center z: -1 // The map will not appear under non-transparent areas. // Other map codes .... } }
Thank you for all. Have a nice coding.