以下是一个基于Qt的倒计时圆环绘制示例:
- 首先,我们需要在Qt中创建一个自定义小部件来实现倒计时圆环的绘制。为此,我们可以使用QPainter类进行绘制操作。
class CountdownWidget : public QWidget
{
public:
CountdownWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
};
- 在paintEvent函数中,我们可以使用QPainter类的方法来实现倒计时圆环的绘制。首先,我们需要计算出圆环上每个刻度线对应的角度值,并将其转换为弧度值。然后,根据当前时间和目标时间之间的差距,确定当前进度所占用的角度,并将其转换为弧度值。最后,根据这些值来绘制圆环。
void CountdownWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
int side = qMin(width(), height());
// 绘制背景
painter.fillRect(rect(), Qt::black);
// 计算刻度线角度
const int numTicks = 60;
const qreal deltaAngle = 360.0 / numTicks;
const qreal halfDeltaAngle = deltaAngle / 2;
QVector<QLineF> tickLines;
for (int i = 0; i < numTicks; ++i) {
QLineF tickLine(0, -side / 2 + 10, 0, -side / 2 + 20);
tickLine.setAngle(i * deltaAngle);
tickLines.append(tickLine);
}
// 绘制刻度线
painter.save();
painter.translate(width() / 2, height() / 2);
painter.setPen(QPen(Qt::white, 3));
for (int i = 0; i < numTicks; ++i) {
painter.drawLine(tickLines[i]);
}
painter.restore();
// 计算进度角度
const int totalSeconds = m_targetTime.secsTo(QDateTime::currentDateTime());
const qreal progressAngle = (360.0 / m_totalSeconds) * totalSeconds;
// 绘制圆环
painter.save();
painter.translate(width() / 2, height() / 2);
QRectF rect(-side / 2 + 30, -side / 2 + 30, side - 60, side - 60);
QPainterPath path;
path.addEllipse(rect);
QPen pen(Qt::white, m_thickness);
pen.setCapStyle(Qt::FlatCap);
qreal startAngle = -90.0;
if (progressAngle > halfDeltaAngle) {
// 绘制进度条
pen.setColor(m_progressColor);
painter.setPen(pen);
qreal endAngle = startAngle + qMin(progressAngle - halfDeltaAngle,
static_cast<qreal>(360.0));
QPainterPath progressPath;
progressPath.arcMoveTo(rect, startAngle);
progressPath.arcTo(rect, startAngle, endAngle - startAngle);
painter.drawPath(progressPath);
startAngle += progressAngle;
if (startAngle < 360.0 - halfDeltaAngle) {
// 绘制未完成部分
pen.setColor(m_backgroundColor);
painter.setPen(pen);
QPainterPath remainderPath;
remainderPath.arcMoveTo(rect, startAngle);
remainderPath.arcTo(rect, startAngle, 360.0 - halfDeltaAngle - startAngle);
painter.drawPath(remainderPath);
}
} else {
// 绘制未完成部分
pen.setColor(m_backgroundColor);
painter.setPen(pen);
qreal endAngle = startAngle + qMin(halfDeltaAngle - progressAngle,
static_cast<qreal>(360.0));
QPainterPath remainderPath;
remainderPath.arcMoveTo(rect, startAngle);
remainderPath.arcTo(rect, startAngle, endAngle - startAngle);
painter.drawPath(remainderPath);
startAngle += halfDeltaAngle;
// 绘制进度条
pen.setColor(m_progressColor);
painter.setPen(pen);
QPainterPath progressPath;
progressPath.arcMoveTo(rect, startAngle);
if (progressAngle > 0) {
progressPath.arcTo(rect, startAngle,
qMin(progressAngle + halfDeltaAngle,
static_cast<qreal>(360.0)) - startAngle);
if (progressAngl > 360.0 - halfDeltaAngel) {
pen.setColor(m_backgroundColor);
painter.setPen(pen);
QPainterpath remainderpath;
remaindertath.arcMoveto(rect, 270.0)
remaindertath.lineTo(-side / 2 +30,-side/2+30)
remaindertath.lineTo(side /2-30,-side/2+30)
painterrawLine(side /2-20,-side/2+30, side /2-20,-side/2+10)
painterrawLine(side /2-30,-side/2+20, side /2-10,-side/2+20)
}
} else {
progressPath.arcTo(rect, startAngle,
halfDeltaAngle - qMax(progressAngle,
static_cast<qreal>(0.0)));
}
painter.drawPath(progressPath);
startAngle += progressAngle + halfDeltaAngle;
}
painter.restore();
}
- 最后,我们需要设置倒计时的目标时间和总共需要的时间,并在每次更新计时器事件发生时重绘小部件。
CountdownWidget::CountdownWidget(QWidget *parent)
: QWidget(parent)
{
m_targetTime = QDateTime::currentDateTime().addSecs(60);
m_totalSeconds = 60;
m_thickness = 12;
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [this]() { update(); });
timer->start(1000);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
CountdownWidget widget;
widget.show();
return app.exec();
}
这样,我们就可以得到一个基于Qt的倒计时圆环绘制示例。