最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt?Qml實(shí)現(xiàn)任意角為圓角的矩形

 更新時(shí)間:2025年01月16日 08:59:53   作者:夢(mèng)起丶  
在?Qml?中,矩形(Rectangle)是最常用的元素之一,本文將介紹如何通過(guò)自定義?Qml?元素實(shí)現(xiàn)一個(gè)任意角可為圓角的矩形,感興趣的可以了解下

在 Qml 中,矩形(Rectangle)是最常用的元素之一。

然而,標(biāo)準(zhǔn)的矩形元素僅允許設(shè)置統(tǒng)一的圓角半徑。

在實(shí)際開(kāi)發(fā)中,我們經(jīng)常需要更靈活的圓角設(shè)置,例如只對(duì)某些角進(jìn)行圓角處理,或者設(shè)置不同角的圓角半徑。

本文將介紹如何通過(guò)自定義 Qml 元素實(shí)現(xiàn)一個(gè)任意角可為圓角的矩形。

效果圖

自定義 Qml 元素:DelRectangle

我們將創(chuàng)建一個(gè)名為 DelRectangle 的自定義 Qml 元素,它繼承自 QQuickPaintedItem,并重寫(xiě)其 paint() 方法來(lái)自定義繪制邏輯。

頭文件(delrectangle.h)

#ifndef DELRECTANGLE_H
#define DELRECTANGLE_H

#include <QQuickPaintedItem>

class DelPen: public QObject
{
    Q_OBJECT
    Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged FINAL)
    Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
    QML_NAMED_ELEMENT(DelPen)
public:
    DelPen(QObject *parent = nullptr);
    qreal width() const;
    void setWidth(qreal width);
    QColor color() const;
    void setColor(const QColor &color);
    bool isValid() const;
signals:
    void widthChanged();
    void colorChanged();
private:
    qreal m_width = 1;
    QColor m_color = Qt::transparent;
};

class DelRectangle: public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged FINAL)
    Q_PROPERTY(qreal topLeftRadius READ topLeftRadius WRITE setTopLeftRadius NOTIFY topLeftRadiusChanged FINAL)
    Q_PROPERTY(qreal topRightRadius READ topRightRadius WRITE setTopRightRadius NOTIFY topRightRadiusChanged FINAL)
    Q_PROPERTY(qreal bottomLeftRadius READ bottomLeftRadius WRITE setBottomLeftRadius NOTIFY bottomLeftRadiusChanged FINAL)
    Q_PROPERTY(qreal bottomRightRadius READ bottomRightRadius WRITE setBottomRightRadius NOTIFY bottomRightRadiusChanged FINAL)
    Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
    Q_PROPERTY(DelPen* border READ border CONSTANT)
    QML_NAMED_ELEMENT(DelRectangle)
public:
    explicit DelRectangle(QQuickItem *parent = nullptr);
    ~DelRectangle();
    qreal radius() const;
    void setRadius(qreal radius);
    qreal topLeftRadius() const;
    void setTopLeftRadius(qreal radius);
    qreal topRightRadius() const;
    void setTopRightRadius(qreal radius);
    qreal bottomLeftRadius() const;
    void setBottomLeftRadius(qreal radius);
    qreal bottomRightRadius() const;
    void setBottomRightRadius(qreal radius);
    QColor color() const;
    void setColor(QColor color);
    DelPen *border();
    void paint(QPainter *painter) override;
signals:
    void radiusChanged();
    void topLeftRadiusChanged();
    void topRightRadiusChanged();
    void bottomLeftRadiusChanged();
    void bottomRightRadiusChanged();
    void colorChanged();
private:
    Q_DECLARE_PRIVATE(DelRectangle);
    QSharedPointer<DelRectanglePrivate> d_ptr;
};

#endif // DELRECTANGLE_H

實(shí)現(xiàn)文件(delrectangle.cpp)

#include "delrectangle.h"

#include <QPainter>
#include <QPainterPath>
#include <private/qqmlglobal_p.h>

class DelRectanglePrivate
{
public:
    QColor m_color = { 0xffffff };
    DelPen *m_pen = nullptr;
    qreal m_radius = 0;
    qreal m_topLeftRadius = 0;
    qreal m_topRightRadius = 0;
    qreal m_bottomLeftRadius = 0;
    qreal m_bottomRightRadius = 0;
};

DelRectangle::DelRectangle(QQuickItem *parent)
    : QQuickPaintedItem{parent}
    , d_ptr(new DelRectanglePrivate)
{
}

DelRectangle::~DelRectangle()
{
}

qreal DelRectangle::radius() const
{
    Q_D(const DelRectangle);
    return d->m_radius;
}

void DelRectangle::setRadius(qreal radius)
{
    Q_D(DelRectangle);
    if (d->m_radius != radius) {
        d->m_radius = radius;
        d->m_topLeftRadius = radius;
        d->m_topRightRadius = radius;
        d->m_bottomLeftRadius = radius;
        d->m_bottomRightRadius = radius;
        emit radiusChanged();
        update();
    }
}

// 其他 getter 和 setter 方法省略...

QColor DelRectangle::color() const
{
    Q_D(const DelRectangle);
    return d->m_color;
}

void DelRectangle::setColor(QColor color)
{
    Q_D(DelRectangle);
    if (d->m_color != color) {
        d->m_color = color;
        emit colorChanged();
        update();
    }
}

DelPen *DelRectangle::border()
{
    Q_D(DelRectangle);
    if (!d->m_pen) {
        d->m_pen = new DelPen;
        QQml_setParent_noEvent(d->m_pen, this);
        connect(d->m_pen, &DelPen::colorChanged, this, [this]{ update(); });
        connect(d->m_pen, &DelPen::widthChanged, this, [this]{ update(); });
        update();
    }
    return d->m_pen;
}

void DelRectangle::paint(QPainter *painter)
{
    Q_D(DelRectangle);
    painter->save();
    painter->setRenderHint(QPainter::Antialiasing);
    QRectF rect = boundingRect();
    if (d->m_pen && d->m_pen->isValid()) {
        rect = boundingRect();
        if (rect.width() > d->m_pen->width() * 2) {
            auto dx = d->m_pen->width() * 0.5;
            rect.adjust(dx, 0, -dx, 0);
        }
        if (rect.height() > d->m_pen->width() * 2) {
            auto dy = d->m_pen->width() * 0.5;
            rect.adjust(0, dy, 0, -dy);
        }
        painter->setPen(QPen(d->m_pen->color(), d->m_pen->width(), Qt::SolidLine, Qt::SquareCap, Qt::SvgMiterJoin));
    }
    QPainterPath path;
    path.moveTo(rect.bottomRight() - QPointF(0, d->m_bottomRightRadius));
    path.lineTo(rect.topRight() + QPointF(0, d->m_topRightRadius));
    path.arcTo(QRectF(QPointF(rect.topRight() - QPointF(d->m_topRightRadius * 2, 0)), QSize(d->m_topRightRadius * 2, d->m_topRightRadius * 2)), 0, 90);
    path.lineTo(rect.topLeft() + QPointF(d->m_topLeftRadius, 0));
    path.arcTo(QRectF(QPointF(rect.topLeft()), QSize(d->m_topLeftRadius * 2, d->m_topLeftRadius * 2)), 90, 90);
    path.lineTo(rect.bottomLeft() - QPointF(0, d->m_bottomLeftRadius));
    path.arcTo(QRectF(QPointF(rect.bottomLeft().x(), rect.bottomLeft().y() - d->m_bottomLeftRadius * 2), QSize(d->m_bottomLeftRadius * 2, d->m_bottomLeftRadius * 2)), 180, 90);
    path.lineTo(rect.bottomRight() - QPointF(d->m_bottomRightRadius, 0));
    path.arcTo(QRectF(QPointF(rect.bottomRight() - QPointF(d->m_bottomRightRadius * 2, d->m_bottomRightRadius * 2)), QSize(d->m_bottomRightRadius * 2, d->m_bottomRightRadius * 2)), 270, 90);
    painter->setBrush(d->m_color);
    painter->drawPath(path);
    painter->restore();
}

關(guān)鍵點(diǎn)解析

自定義 Qml 元素:通過(guò)繼承 QQuickPaintedItem 并使用 QML_NAMED_ELEMENT 宏,我們可以將自定義的 C++ 類(lèi)注冊(cè)為 Qml 元素。

屬性定義:我們定義了多個(gè)屬性來(lái)控制矩形的圓角半徑和顏色,例如 radius、topLeftRadiuscolor 等,并提供了相應(yīng)的 getter 和 setter 方法。

邊框管理:通過(guò) DelPen 類(lèi)來(lái)管理矩形的邊框樣式,包括邊框顏色和寬度。

繪制邏輯:在 paint() 方法中,我們使用 QPainterPath 來(lái)繪制具有不同圓角的矩形。通過(guò)組合使用直線(xiàn)和弧線(xiàn),我們可以實(shí)現(xiàn)任意角的圓角效果。

使用示例

在 Qml 文件中,我們可以像使用標(biāo)準(zhǔn)的 Rectangle 元素一樣使用 DelRectangle

import QtQuick 2.15
import QtQuick.Window 2.15
import DelegateUI.Controls 1.0

Window {
    visible: true
    width: 400
    height: 300
    title: "DelRectangle Example"

    DelRectangle {
        anchors.centerIn: parent
        width: 200
        height: 150
        color: "lightblue"
        topLeftRadius: 20
        bottomRightRadius: 30
        border {
            width: 2
            color: "blue"
        }
    }
}

總結(jié)

通過(guò)自定義 Qml 元素 DelRectangle,我們實(shí)現(xiàn)了對(duì)矩形圓角的更靈活控制,使其能夠滿(mǎn)足更多實(shí)際開(kāi)發(fā)需求。

要注意的是,在 Qt 6.7 版本以后,內(nèi)置的 Rectangle 將提供同等功能( 作為技術(shù)預(yù)覽 ),并且效果更好:

到此這篇關(guān)于Qt Qml實(shí)現(xiàn)任意角為圓角的矩形的文章就介紹到這了,更多相關(guān)Qt Qml圓角矩形內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)逆序輸出詳細(xì)

    C語(yǔ)言實(shí)現(xiàn)逆序輸出詳細(xì)

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)逆序輸出。主要實(shí)現(xiàn)C語(yǔ)言實(shí)現(xiàn)對(duì)數(shù)組元素依次賦值然后按照逆序輸出,下面文章小編將詳細(xì)解說(shuō),需要的朋友可以參考一下
    2021-10-10
  • C++中std::transform的使用小結(jié)

    C++中std::transform的使用小結(jié)

    std::transform?是 C++ 標(biāo)準(zhǔn)庫(kù)中的一個(gè)算法,本文主要介紹了C++中std::transform的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • VS2022連接sqlserver數(shù)據(jù)庫(kù)教程

    VS2022連接sqlserver數(shù)據(jù)庫(kù)教程

    本文主要介紹了VS2022連接sqlserver數(shù)據(jù)庫(kù)教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • C語(yǔ)言中花式退出程序的方式總結(jié)

    C語(yǔ)言中花式退出程序的方式總結(jié)

    在本篇文章當(dāng)中主要給大家介紹C語(yǔ)言當(dāng)中一些不常用的特性,比如在main函數(shù)之前和之后設(shè)置我們想要執(zhí)行的函數(shù),以及各種花式退出程序的方式,需要的可以參考一下
    2022-10-10
  • C++ 中l(wèi)ambda表達(dá)式的編譯器實(shí)現(xiàn)原理

    C++ 中l(wèi)ambda表達(dá)式的編譯器實(shí)現(xiàn)原理

    C++ 11加入了一個(gè)非常重要的特性——Lambda表達(dá)式。這篇文章主要介紹了C++ 中l(wèi)ambda表達(dá)式的編譯器實(shí)現(xiàn)原理,需要的朋友可以參考下
    2017-02-02
  • C++中分配器allocator的實(shí)現(xiàn)

    C++中分配器allocator的實(shí)現(xiàn)

    本文主要介紹了C++中分配器allocator的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • 用C語(yǔ)言求冪函數(shù)和指數(shù)函數(shù)的方法

    用C語(yǔ)言求冪函數(shù)和指數(shù)函數(shù)的方法

    這篇文章主要介紹了用C語(yǔ)言求冪函數(shù)和指數(shù)函數(shù)的方法,即pow()函數(shù)和sqrt()函數(shù)的使用,需要的朋友可以參考下
    2015-08-08
  • 深度揭秘C++面向?qū)ο缶幊讨欣^承的核心概念

    深度揭秘C++面向?qū)ο缶幊讨欣^承的核心概念

    我們知道C語(yǔ)言是面向過(guò)程的編程語(yǔ)言,C++在C語(yǔ)言的基礎(chǔ)上進(jìn)化出了面向?qū)ο蟮哪P?,而繼承就是面向?qū)ο蟮闹匾獙傩?,下面就讓小編?lái)和大家詳細(xì)講講吧
    2023-07-07
  • C++實(shí)現(xiàn)結(jié)束應(yīng)用進(jìn)程小工具

    C++實(shí)現(xiàn)結(jié)束應(yīng)用進(jìn)程小工具

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)結(jié)束應(yīng)用進(jìn)程小工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • C++?protobuf中對(duì)不同消息內(nèi)容進(jìn)行賦值的方式總結(jié)(set_、set_allocated_、mutable_、add_)

    C++?protobuf中對(duì)不同消息內(nèi)容進(jìn)行賦值的方式總結(jié)(set_、set_allocated_、mutable_、

    這篇文章主要給大家介紹了關(guān)于C++?protobuf中對(duì)不同消息內(nèi)容進(jìn)行賦值的方式總結(jié),主要使用的是set_、set_allocated_、mutable_、add_,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03

最新評(píng)論

孙吴县| 北海市| 阳城县| 昭平县| 贡嘎县| 湘潭县| 道真| 安新县| 南充市| 西林县| 苏州市| 通海县| 怀柔区| 永城市| 民乐县| 乡城县| 东乌珠穆沁旗| 桐城市| 时尚| 凌海市| 岗巴县| 砀山县| 登封市| 南皮县| 搜索| 二手房| 鄂托克前旗| 邵阳市| 佛冈县| 景宁| 历史| 武宣县| 庄浪县| 盐津县| 巧家县| 翁源县| 江北区| 寻乌县| 辽宁省| 佛学| 康马县|