Assign styles to rectangles (Make banner, polygon)



  • Hi all,

    I want to assign style to rectangles.Any ideas on this?The example is on below.

    alt metni

    Thanks.



  • @aktay Canvas in QML/ Qpainter in Qt should be the choice to create polygons.



  • @Yashpal
    Thank you for the post.But I want to embed an object/item in the polygon. Canvas only draws, objects cannot be embed in these drawings.


  • Moderators

    @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.



  • @aktay Okay. Then, you can go with option of extending QML with C++ like ambershark said. Create a class that does polygon creation for you, register it with QML engine and create polygon objects in QML, add children to it.


  • Moderators

    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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.