Qt编写自定义控件:抽奖转盘

#ifndef LOTTERYTURNTABLEWIDGET_H
#define LOTTERYTURNTABLEWIDGET_H

#include <QWidget>

class LotteryTurntableWidget : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(int rotate READ getRotate WRITE setRotate MEMBER painterRotate)

public:
    LotteryTurntableWidget(QWidget *parent = nullptr);
    ~LotteryTurntableWidget()override;
    int getRotate();
    void setRotate(int rotate);

protected:
    void paintEvent(QPaintEvent *event)override;
    void mousePressEvent(QMouseEvent *event)override;
    void mouseReleaseEvent(QMouseEvent *event)override;

private:
    QRect centerBtnRect;
    bool isPressCenterBtn{false};
    bool isRuning{false};
    int painterRotate{0};
    void onRotateFinished();
    QList<Qt::GlobalColor> colorList;
};
#endif // LOTTERYTURNTABLEWIDGET_H
#include "lotteryturntablewidget.h"
#include <QPainter>
#include <QPaintEvent>
#include <QPainterPath>
#include <QTime>
#include <QDebug>
#include <QRandomGenerator>
#include <QPropertyAnimation>

LotteryTurntableWidget::LotteryTurntableWidget(QWidget *parent)
    : QWidget(parent)
{
    setPalette(Qt::white);
    setMinimumSize(500,500);

    colorList << Qt::red << Qt::yellow << Qt::green << Qt::cyan << Qt::blue << Qt::magenta << Qt::darkGreen << Qt::darkCyan;
}

LotteryTurntableWidget::~LotteryTurntableWidget()
{
}

int LotteryTurntableWidget::getRotate()
{
    return painterRotate;
}

void LotteryTurntableWidget::setRotate(int rotate)
{
    painterRotate = rotate;
    update();
}

void LotteryTurntableWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);  //反走样开启
    const auto rect = event->rect();
    auto radius = std::min(rect.width(),rect.height()) / 2 - 25;

    painter.save();
    painter.translate(rect.center()); //将坐标系的原点设置为(r,r)

    QPen pen;
    pen.setColor(QColor("#F0630B"));
    pen.setWidth(16);
    painter.setPen(pen);
    painter.drawEllipse(QPoint(0, 0), radius, radius);

    pen.setColor(QColor("#FF4500"));
    pen.setWidth(8);
    painter.setPen(pen);
    radius -= 8;
    painter.drawEllipse(QPoint(0, 0), radius, radius);

    pen.setColor(QColor("#B71606"));
    pen.setWidth(40);
    painter.setPen(pen);
    radius -= 24;
    painter.drawEllipse(QPoint(0, 0), radius, radius);

    painter.save();
    if(!isRuning)
    {
        painter.setPen(Qt::white);
        painter.setBrush(Qt::white);
    }
    for (int i = 0; i < 20; ++i)
    {
        painter.rotate(18.0);
        int smallEllipse;
        if(i % 2 == 0)
        {
            if(isRuning)
            {
                if(painterRotate % 2 == 0)
                {
                    painter.setPen(Qt::red);
                    painter.setBrush(Qt::red);
                }
                else
                {
                    painter.setPen(Qt::blue);
                    painter.setBrush(Qt::blue);
                }
            }
            smallEllipse = 15;
        }
        else
        {
            if(isRuning)
            {
                if(painterRotate % 2 == 0)
                {
                    painter.setPen(Qt::blue);
                    painter.setBrush(Qt::blue);
                }
                else
                {
                    painter.setPen(Qt::red);
                    painter.setBrush(Qt::red);
                }
            }
            smallEllipse = 10;
        }
        painter.drawEllipse(QPoint(radius, 0), smallEllipse, smallEllipse);
    }
    painter.restore();

    pen.setColor(QColor("#FFC228"));
    pen.setWidth(20);
    painter.setPen(pen);
    radius -= 30;
    painter.drawEllipse(QPoint(0, 0), radius, radius);

    radius -= 10;
    auto centerRect = QRect(-radius,-radius,radius * 2,radius * 2);

    painter.setPen(Qt::transparent);
    painter.save();
    painter.rotate(18.0 * painterRotate);
    for (int i = 0;i < 8;++i)
    {
        QPainterPath path;
        path.moveTo(0,0);
        path.arcTo(centerRect, 45 * i,45);
        path.closeSubpath();
        painter.fillPath(path,colorList[i]);
    }    
    painter.restore();

    QPainterPath trianglePath;//三角形
    QPolygon polygon;
    polygon.append(QPoint(0,-radius * 0.55));
    polygon.append(QPoint(-radius * 0.25,0));
    polygon.append(QPoint(radius * 0.25,0));
    trianglePath.addPolygon(polygon);
    painter.setBrush(QColor("#EEDAA2"));
    painter.drawPath(trianglePath);

    painter.setBrush(QColor("#FDFAEA"));
    radius = static_cast<int>(radius * 0.3);
    painter.drawEllipse(QPoint(0, 0), radius, radius);

    painter.setBrush(isPressCenterBtn ? QColor("#B91A0D").lighter() : QColor("#B91A0D"));//中间的按钮
    radius -= 2;
    painter.drawEllipse(QPoint(0, 0), radius, radius);

    centerBtnRect = QRect(rect.width() / 2 - radius,rect.height() / 2 - radius,radius * 2,radius * 2);
    painter.restore();
}

void LotteryTurntableWidget::mousePressEvent(QMouseEvent *event)
{
    if(isRuning)
    {
        QWidget::mousePressEvent(event);
        return;
    }
    QRegion ellipseRegion(centerBtnRect, QRegion::Ellipse);
    isPressCenterBtn = ellipseRegion.contains(event->pos());
    if(isPressCenterBtn)
    {
        isRuning = true;

        QPropertyAnimation *animation = new QPropertyAnimation(this, "rotate");
        animation->setEasingCurve(QEasingCurve::InOutCubic);
        animation->setDuration(3000);
        animation->setStartValue(0);
        animation->setEndValue(QRandomGenerator::global()->bounded(360) + 360 * 5);
        connect(animation, &QAbstractAnimation::finished, this, &LotteryTurntableWidget::onRotateFinished);
        animation->start(QAbstractAnimation::DeleteWhenStopped);
        update();
    }
    QWidget::mousePressEvent(event);
}

void LotteryTurntableWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(isPressCenterBtn)
    {
        isPressCenterBtn = false;
        update();
    }
    QWidget::mouseReleaseEvent(event);
}

void LotteryTurntableWidget::onRotateFinished()
{
    isRuning = false;
}

效果:

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值