qt - 使用 QPainter 实例化绘图

Posted

技术标签:

【中文标题】qt - 使用 QPainter 实例化绘图【英文标题】:qt - instantiate a drawing with QPainter 【发布时间】:2020-04-25 21:46:54 【问题描述】:

所以我用 QPainter 画了一个圆圈。

我的问题是:我可以将那个圆圈保存在变量中以便我可以使用它吗? 我想用圆圈制作动画。

QPainter painter(this);
painter.setPen(dottedPen);
painter.drawEllipse(QRect(160,260,80,80));

【问题讨论】:

dottedPen 被声明:QPen dottedPen(QBrush(QColor(255,0,0)),2,Qt::DashDotLine); 【参考方案1】:

您可以使用所需的所有属性为 Ellipse 实现自己的类。然后为您的任何财产设置QPropertyAnimation。这是一个小例子。 Ellipse 类(具有 4 个自定义属性):

class Ellipse : public QObject

    Q_OBJECT
    Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged)
    Q_PROPERTY(QPoint center READ center WRITE setCenter NOTIFY centerChanged)
    Q_PROPERTY(int radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
    Q_PROPERTY(int radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
public:
    explicit Ellipse(QObject *parent = 0);

    void setWidgetToPaint(QWidget* widget);

    void paint();

    void setVisible(const bool visible);
    bool visible() const;

    void setCenter(const QPoint& center);
    const QPoint& center() const;

    void setRadiusX(const int rx);
    int radiusX() const;

    void setRadiusY(const int ry);
    int radiusY() const;

signals:
    void centerChanged();
    void radiusXChanged();
    void radiusYChanged();
    void visibleChanged();

public slots:

private:
    QPointer<QWidget> m_widgetToPaint;
    bool m_isVisible;
    QPoint m_center;
    int m_rx;
    int m_ry;
;

Ellipse::Ellipse(QObject *parent) :
    QObject(parent),
    m_widgetToPaint(nullptr),
    m_isVisible(false),
    m_rx(1),
    m_ry(1)



void Ellipse::setWidgetToPaint(QWidget *widget)

    m_widgetToPaint = widget;
    if (widget)
    
        connect(this, SIGNAL(visibleChanged()), m_widgetToPaint.data(), SLOT(repaint()));
        connect(this, SIGNAL(centerChanged()), m_widgetToPaint.data(), SLOT(repaint()));
        connect(this, SIGNAL(radiusXChanged()), m_widgetToPaint.data(), SLOT(repaint()));
        connect(this, SIGNAL(radiusYChanged()), m_widgetToPaint.data(), SLOT(repaint()));
    


void Ellipse::paint()

    if(!m_widgetToPaint)
    
        return;
    

    if (!m_isVisible)
    
        return;
    

    QPainter painter(m_widgetToPaint);
    painter.drawEllipse(m_center, m_rx, m_ry);


void Ellipse::setCenter(const QPoint &center)

    bool needNotify = m_center != center;
    m_center = center;
    if (needNotify)
    
        emit centerChanged();
    


const QPoint & Ellipse::center() const

    return m_center;


void Ellipse::setRadiusX(const int rx)

    bool needNotify = m_rx != rx;
    m_rx = rx;
    if (needNotify)
    
        emit radiusXChanged();
    


int Ellipse::radiusX() const

    return m_rx;


void Ellipse::setRadiusY(const int ry)

    bool needNotify = m_ry != ry;
    m_ry = ry;
    if (needNotify)
    
        emit radiusYChanged();
    


int Ellipse::radiusY() const

    return m_ry;


void Ellipse::setVisible(const bool visible)

    bool needNotify = m_isVisible != visible;
    m_isVisible = visible;
    if (needNotify)
    
        emit visibleChanged();
    


bool Ellipse::visible() const

    return m_isVisible;

现在在您的小部件中创建一个椭圆实例。并重新实现 paintEvent 您的小部件

class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void paintEvent(QPaintEvent *event);

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::MainWindow *ui;
    Ellipse m_ellipse;
;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)

    ui->setupUi(this);
    m_ellipse.setWidgetToPaint(this);


void MainWindow::paintEvent(QPaintEvent *event)

    QMainWindow::paintEvent(event);
    m_ellipse.paint();

要让椭圆现在可见,只需设置visible=true

void MainWindow::on_pushButton_clicked()

    m_ellipse.setVisible(true);
    m_ellipse.setCenter(QPoint(30, 30));
    m_ellipse.setRadiusX(25);
    m_ellipse.setRadiusY(15);

现在您还可以为自定义属性设置任何动画。这是center 属性的示例

void MainWindow::on_pushButton_2_clicked()

    QPropertyAnimation *animationCenter = new QPropertyAnimation(&m_ellipse, "center", this);
    animationCenter->setStartValue(QPoint(30, 30));
    animationCenter->setEndValue(QPoint(100, 100));
    animationCenter->setDuration(3000);
    animationCenter->start(QAbstractAnimation::DeleteWhenStopped);

【讨论】:

我粘贴了你的代码我有一个小问题:编译器说连接函数:没有匹配的成员函数调用“连接”我继承了 QObject 并且我有 Q_OBJECT 宏 尝试重建项目或将connect调用更改为connect(this, &amp;Ellipse::visibleChanged, m_widgetToPaint.data(), &amp;QWidget::repaint)等新式声明 好的,现在可以使用了!这是我项目的完美解决方案!谢谢

以上是关于qt - 使用 QPainter 实例化绘图的主要内容,如果未能解决你的问题,请参考以下文章

使用带有移动对象的 OpenGL 实例化绘图

OpenGL实例化数组绘图

从一个实例来看QMutex的使用

OpenGL实例化绘图如何处理顶点输入限制

在 GPU 上实例化更快吗?

Qt中QPainter的使用