Qt 小部件 C++ 中的自定义圆形倒计时进度条

问题描述 投票:0回答:1

我想要一个循环时间计数器来显示进程的剩余时间,如下图所示 我使用 Qty 6.6.3 和 Qty 小部件 如果有人有想法这样做,如果你能帮助我,我将不胜感激。

Custum circular time counter

我写了类似于我想要的代码,但是这个模型正在加载,用户看不到剩余时间。


CircleLoadingWidget.cpp

#include <QtGui/qpainter.h>
#include <QtWidgets/qapplication.h>
#include "circle_loading_widget.h"


CircleLoadingWidget::CircleLoadingWidget(QWidget *parent)
    : QWidget(parent)
    , background(Qt::transparent)
    , timerId(0)
{
}


CircleLoadingWidget::~CircleLoadingWidget()
{
}


void CircleLoadingWidget::setColors(const QList<QColor> &colors)
{
    this->colors = colors;
    if (timerId) {
        update();
    }
}


QColor CircleLoadingWidget::getColor(int i)
{
    if (colors.size() > i) {
        return colors.at(i);
    } else {
        switch (i) {
        case 0:
            return QColor("#dc322f");
        case 1:
            return QColor("#268bd2");
        default:
            return QColor("#90CAF9");
        }
    }
}


void CircleLoadingWidget::setBackground(const QBrush &background)
{
    this->background = background;
    if (timerId) {
        update();
    }
}


void CircleLoadingWidget::start()
{
    if (!timerId) {
        timerId = startTimer(1000 / 60);
        timer.restart();
    }
}


void CircleLoadingWidget::stop()
{
    if (timerId) {
        killTimer(timerId);
        timerId = 0;
    }
}


void CircleLoadingWidget::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    qint64 msecs = timer.elapsed();
    msecs %= 5000;
    bool inverted;
    if (msecs > 2500) {
        msecs = msecs - 2500;
        inverted = true;
    } else {
        inverted = false;
    }
    QEasingCurve headCurve(QEasingCurve::OutQuart);
    QEasingCurve tailCurve(QEasingCurve::InQuad);

    QRect r0 = rect();
    if (r0.width() > r0.height()) {
        r0.setWidth(r0.height());
    } else {
        r0.setHeight(r0.width());
    }
    r0.moveCenter(rect().center());
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(background);
    painter.setPen(background.color());
    painter.drawRect(rect());
    for (int i = 0; i < 1; ++i) {
        qreal k1 = qMin(msecs / (1000.0 + 1000.0 / 10 * i), 1.0);
        qreal k2 = qMin(msecs / (1500.0 + 1000.0 / 10 * i), 1.0);
        if (qFuzzyCompare(k1, k2)) {
            continue;
        }

        qreal headAngle, tailAngle, spanAngle;
        if (inverted) {
            headAngle = 90 - headCurve.valueForProgress(k1) * 360;
            tailAngle = 90 - tailCurve.valueForProgress(k2) * 360;
        } else {
            headAngle = headCurve.valueForProgress(k1) * 360 + 90;
            tailAngle = tailCurve.valueForProgress(k2) * 360 + 90;
        }
        spanAngle =  tailAngle - headAngle;

        QRect r1 = r0 ;
        r1.setSize(r0.size() * (0.1 * (10 - i)));
        r1.moveCenter(r0.center());
        QRect r2 = r0;
        r2.setSize(r0.size() * (0.1 * (9 - i) + 0.01));
        r2.moveCenter(r0.center());

        qreal l1 = 1.0 - headCurve.valueForProgress(k1);
        qreal l3 = tailCurve.valueForProgress(k1);
        qreal l2 = 1.0 - l1 - l3;

        painter.setBrush(getColor(0));
        painter.drawPie(r1, headAngle * 16, spanAngle * 16 * l1 * 0.9);
        painter.setBrush(background);
        painter.drawPie(r2, headAngle * 16, spanAngle * 16 * l1 * 0.9);

        painter.setBrush(getColor(1));
        painter.drawPie(r1, headAngle * 16 + spanAngle * 16 * l1, spanAngle * 16 * l2 * 0.9);
        painter.setBrush(background);
        painter.drawPie(r2, headAngle * 16 + spanAngle * 16 * l1, spanAngle * 16 * l2 * 0.9);

        painter.setBrush(getColor(2));
        painter.drawPie(r1, headAngle * 16 + spanAngle * 16 * (l1 + l2), spanAngle * 16 * l3 * 0.9);
        painter.setBrush(background);
        painter.drawPie(r2, headAngle * 16 + spanAngle * 16 * (l1 + l2), spanAngle * 16 * l3 * 0.9);
    }
}



void CircleLoadingWidget::timerEvent(QTimerEvent *event)
{
    if (event->timerId() != timerId) {
        QWidget::timerEvent(event);
        return;
    }
    update();
}

CircleLoadingWidget.h

#ifndef CIRCLELOADINGWIDGET_H
#define CIRCLELOADINGWIDGET_H

#include <QtCore/qtimer.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qeasingcurve.h>
#include <QtWidgets/qwidget.h>


class CircleLoadingWidget : public QWidget
{
    Q_OBJECT
public:
    explicit CircleLoadingWidget(QWidget *parent = nullptr);
    virtual ~CircleLoadingWidget() override;
public:
    void setColors(const QList<QColor> &colors);
    void setBackground(const QBrush &background);
    void start();
    void stop();
protected:
    virtual void paintEvent(QPaintEvent *event) override;
    virtual void timerEvent(QTimerEvent *event) override;
private:
    QColor getColor(int i);
private:
    QList<QColor> colors;
    QBrush background;
    QElapsedTimer timer;
    int timerId;
};


#endif // CIRCLELOADINGWIDGET_H

结果是这样的(有加载动画,用户看不到剩余时间和进程):

enter image description hereenter image description here

c++ qt counter qtwidgets
1个回答
0
投票

您得到的结果与第一张图像有很大不同,因此并不完全清楚您想要实现什么目标。实际上,对于第一张图片,我会执行以下操作:

class Gauge: public QWidget
{
public:
    Gauge(QWidget *parent = nullptr)
        : QWidget(parent)
    {}
    
    void setValue(int value)
    {
        if (value != m_value) {
            m_value = qBound(0, value, 100);
            update();
        }
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.fillRect(rect(), Qt::white);
        
        int size = qMin(width(), height()) - 40;
        QRectF rect(20, 20, size, size);
        
        QPen pen(QColor::fromString("#eaeaea"), 20, Qt::SolidLine, Qt::RoundCap);
        painter.setPen(pen);
        painter.drawEllipse(rect);
        
        pen.setColor(QColor::fromString("#4a62ad"));
        painter.setPen(pen);
        painter.drawArc(rect, 90 * 16, -m_value * 16 * 3.6);
        
        painter.setPen(QColor::fromString("#333333"));
        QFont font = painter.font();
        font.setBold(true);
        font.setPointSize(size / 5);
        painter.setFont(font);
        painter.drawText(rect, Qt::AlignCenter, QString::number(m_value) + "%");
    }

private:
    int m_value{0};
};

可能应该是这样的:

enter image description here

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.