【问题标题】:How to extend QML Rectangle in C++如何在 C++ 中扩展 QML 矩形
【发布时间】:2014-06-29 20:42:03
【问题描述】:

当我想在 C++ 中创建一个新的 Qt Quick Item 时,我扩展了 QQuickItem。碰巧我希望我的新项目具有与矩形相同的基本属性。有没有我可以直接扩展为 Rectangle 的类?

【问题讨论】:

    标签: qt qml qtquick2 qt-quick


    【解决方案1】:

    矩形实际上是QQuickRectangle,但它没有被导出以在C++中使用。头文件是QtQuick\private\qquickrectangle_p.h

    【讨论】:

    • 那么,在包含它之后,我们应该按照extension procedure 获得一个工作组件?
    • @CapelliC,该类未在 Qt5Quick.lib 中导出。所以它不是为在 C++ 中使用而设计的。您需要修改包含文件以导出类(或定义 Q_AUTOTEST_EXPORT,如qt-project.org/wiki/Qt_Autotest_Environment 中所述),然后重建 Qt5Quick.lib 以便能够在 C++ 中使用它。
    【解决方案2】:

    检查我的AdvancedRectangle 版本,每个角可以有不同的半径。我不得不重新实现 Rectangle 的行为。

    高级矩形.h

    #ifndef ADVANCEDRECTANGLE_H
    #define ADVANCEDRECTANGLE_H
    
    #include <QQuickPaintedItem>
    #include <QPainter>
    #include <QPen>
    
    class AdvancedRectangle : public QQuickPaintedItem
    {
        Q_OBJECT
    public:
        explicit AdvancedRectangle(QQuickItem *parent = 0);
    
        Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
        QColor color() const;
        void setColor(QColor color);
    
        Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
        qreal radius() const;
        void setRadius(qreal r);
    
        Q_PROPERTY(qreal radiusTopLeft READ radiusTopLeft WRITE setRadiusTopLeft NOTIFY radiusTopLeftChanged)
        qreal radiusTopLeft() const;
        void setRadiusTopLeft(qreal r);
    
        Q_PROPERTY(qreal radiusTopRight READ radiusTopRight WRITE setRadiusTopRight NOTIFY radiusTopRightChanged)
        qreal radiusTopRight() const;
        void setRadiusTopRight(qreal r);
    
        Q_PROPERTY(qreal radiusBottomRight READ radiusBottomRight WRITE setRadiusBottomRight NOTIFY radiusBottomRightChanged)
        qreal radiusBottomRight() const;
        void setRadiusBottomRight(qreal r);
    
        Q_PROPERTY(qreal radiusBottomLeft READ radiusBottomLeft WRITE setRadiusBottomLeft NOTIFY radiusBottomLeftChanged)
        qreal radiusBottomLeft() const;
        void setRadiusBottomLeft(qreal r);
    
        void paint(QPainter *painter);
    
        enum START_ANGELS {
            START_E = 0,
            START_N = 90,
            START_W = 180,
            START_S = 270
        };
    
    signals:
        void colorChanged();
        void radiusChanged();
        void radiusTopLeftChanged();
        void radiusTopRightChanged();
        void radiusBottomRightChanged();
        void radiusBottomLeftChanged();
    
    public slots:
    
    
    private:
        QColor color_ = QColor(255, 255, 255);
        qreal radius_ = 0.0;
        qreal radiusTopLeft_ = -1;
        qreal radiusTopRight_ = -1;
        qreal radiusBottomRight_ = -1;
        qreal radiusBottomLeft_ = -1;
    
    private slots:
        void onAppearanceChanged();
    };
    
    #endif // ADVANCEDRECTANGLE_H
    

    高级矩形.cpp

    #include "advancedrectangle.h"
    
    AdvancedRectangle::AdvancedRectangle(QQuickItem *parent) :
        QQuickPaintedItem(parent)
    {
        connect(this, SIGNAL(widthChanged()), SLOT(onAppearanceChanged()));
        connect(this, SIGNAL(heightChanged()), SLOT(onAppearanceChanged()));
        connect(this, SIGNAL(colorChanged()), SLOT(onAppearanceChanged()));
    }
    
    QColor AdvancedRectangle::color() const
    {
        return color_;
    }
    
    void AdvancedRectangle::setColor(QColor color)
    {
        if (color_ == color) return;
    
        color_ = color;
        emit colorChanged();
    }
    
    qreal AdvancedRectangle::radius() const
    {
        return radius_;
    }
    
    void AdvancedRectangle::setRadius(qreal r)
    {
        if (r == radius_) return;
    
        radius_ = r;
        emit radiusChanged();
    }
    
    qreal AdvancedRectangle::radiusTopLeft() const
    {
        if (radiusTopLeft_ >= 0) return radiusTopLeft_;
        else return radius_;
    }
    
    void AdvancedRectangle::setRadiusTopLeft(qreal r)
    {
        if (r == radiusTopLeft_) return;
    
        radiusTopLeft_ = r;
        emit radiusTopLeftChanged();
    }
    
    qreal AdvancedRectangle::radiusTopRight() const
    {
        if (radiusTopRight_ >= 0) return radiusTopRight_;
        else return radius_;
    }
    
    void AdvancedRectangle::setRadiusTopRight(qreal r)
    {
        if (r == radiusTopRight_) return;
    
        radiusTopRight_ = r;
        emit radiusTopRightChanged();
    }
    
    qreal AdvancedRectangle::radiusBottomRight() const
    {
        if (radiusBottomRight_ >= 0) return radiusBottomRight_;
        else return radius_;
    }
    
    void AdvancedRectangle::setRadiusBottomRight(qreal r)
    {
        if (r == radiusBottomRight_) return;
    
        radiusBottomRight_ = r;
        emit radiusBottomRightChanged();
    }
    
    qreal AdvancedRectangle::radiusBottomLeft() const
    {
        if (radiusBottomLeft_ >= 0) return radiusBottomLeft_;
        else return radius_;
    }
    
    void AdvancedRectangle::setRadiusBottomLeft(qreal r)
    {
        if (r == radiusBottomLeft_) return;
    
        radiusBottomLeft_ = r;
        emit radiusBottomLeftChanged();
    }
    
    void AdvancedRectangle::paint(QPainter *painter)
    {
        QPen pen(Qt::NoPen);
        painter->setPen(pen);
    
        QBrush brush(color_);
        painter->setBrush(brush);
    
        painter->setRenderHints(QPainter::Antialiasing, true);
    
        int _width = width();
        int _height = height();
    
        QRectF rectangle;
        // top-left
        rectangle = QRectF(0, 0, 2*radiusTopLeft(), 2*radiusTopLeft());
        painter->drawPie(rectangle, START_W * 16, 90 * -1 * 16);
    
        // top-right
        rectangle = QRectF(_width-2*radiusTopRight(), 0, 2*radiusTopRight(), 2*radiusTopRight());
        painter->drawPie(rectangle, START_N * 16, 90 * -1 * 16);
    
        // bottom-right
        rectangle = QRectF(_width-2*radiusBottomRight(), _height-2*radiusBottomRight(), 2*radiusBottomRight(), 2*radiusBottomRight());
        painter->drawPie(rectangle, START_E * 16, 90 * -1 * 16);
    
        // bottom-left
        rectangle = QRectF(0, _height-2*radiusBottomLeft(), 2*radiusBottomLeft(), 2*radiusBottomLeft());
        painter->drawPie(rectangle, START_S * 16, 90 * -1 * 16);
    
        QPointF points[12] = {
            QPointF(radiusTopLeft(), 0),
            QPointF(radiusTopLeft(), radiusTopLeft()),
            QPointF(0, radiusTopLeft()),
            QPointF(0, _height-radiusBottomLeft()),
            QPointF(radiusBottomLeft(), _height-radiusBottomLeft()),
            QPointF(radiusBottomLeft(), _height),
            QPointF(_width-radiusBottomRight(), _height),
            QPointF(_width-radiusBottomRight(), _height-radiusBottomRight()),
            QPointF(_width, _height-radiusBottomRight()),
            QPointF(_width, radiusTopRight()),
            QPointF(_width-radiusTopRight(), radiusTopRight()),
            QPointF(_width-radiusTopRight(), 0)
        };
        painter->drawPolygon(points, 12);
    }
    
    void AdvancedRectangle::onAppearanceChanged()
    {
        int new_width = width();
        int new_height = height();
        update(QRect(0, 0, new_width, new_height));
    }
    

    如果您需要获得 MIT 许可,请告诉我。

    【讨论】:

    • 这不是Rectangle 的重新实现,而是AdvancedRectangle 的实现。 RectangleQQuickItemAdvancedRectangleQQuickPaintedItem
    • 你能解释一下如何使用opengl创建我们的自定义qt快速类型,比如文章中的rendering fbos示例吗?
    • 简单有效。这种方法的缺点是它不会被 GPU 加速,因为一切都是在 CPU 上使用 QPainter 绘制的。当您需要很多人在场景中时,不推荐使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    • 2016-10-11
    • 2019-07-18
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多