QT实现自定义控件

最近在看自定义控件,感觉非常炫酷好看,然后自己尝试了一下,欢迎交流讨论,效果如下所示:

代码效果展示

当你按下按钮可以改变仪表盘的速度,也可以改变小鸡孵化的速度:

参考链接:
qt程序实现多个图片连续显示效果像动画一样_qgraphicsscene多幅图片依次显示-CSDN博客
Qt实现仪表盘-自定义控件-CSDN博客

需要注意的是weight的提升,以及painter的使用。

下面是核心代码:

#include "dashboardwidget.h"

#include <QPainter>
#include <QPropertyAnimation>
#include <QtMath>

struct DashBoardWidgetPrivate{
    int maxValue = 100;
    int minValue = 0;
    double startAngle = -50;
    double endAngle = 230;
    int value = minValue;
    int scaleMajor = 10;
    int scaleMinor = 5;
    QString unit = "unit";
    QString text = "test";

    QColor arcColor = QColor(56, 61, 74);
    QColor scaleColor = QColor(4, 168, 173);
    QColor pointerColor = QColor(4, 181, 200);
    QColor textColor = QColor(144, 133, 116);
    QColor backgroundColor = Qt::transparent;
    QPropertyAnimation *animation;
};

DashBoardWidget::DashBoardWidget(QWidget *parent)
    : QWidget(parent)
    , d(new DashBoardWidgetPrivate)
{
    d->animation = new QPropertyAnimation(this, "value", this);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    connect(this, &DashBoardWidget::valueChanged, this, &DashBoardWidget::onStartAnimation);
}

DashBoardWidget::~DashBoardWidget()
{
}

QSize DashBoardWidget::sizeHint() const
{
    return QSize(300, 300);
}

QSize DashBoardWidget::minimumSizeHint() const
{
    return QSize(200, 200);
}

void DashBoardWidget::setMin(const double min)
{
    d->minValue = min;
    update();
}

double DashBoardWidget::min() const
{
    return d->minValue;
}

void DashBoardWidget::setmax(const double max)
{
    d->maxValue = max;
    update();
}

double DashBoardWidget::max() const
{
    return d->maxValue;
}

void DashBoardWidget::setStartAngle(const double startAngle)
{
    d->startAngle = startAngle;
    update();
}

double DashBoardWidget::startAngle() const
{
    return d->startAngle;
}

void DashBoardWidget::setEndAngle(const double endAngle)
{
    d->endAngle = endAngle;
    update();
}

double DashBoardWidget::endAngle() const
{
    return d->endAngle;
}

void DashBoardWidget::setScaleMajor(const int scale)
{
    d->scaleMajor = scale;
    update();
}

int DashBoardWidget::scaleMajor() const
{
    return d->scaleMajor;
}

void DashBoardWidget::setScaleMinor(const int scale)
{
    d->scaleMinor = scale;
    update();
}

int DashBoardWidget::scaleMinor() const
{
    return d->scaleMinor;
}

void DashBoardWidget::setUnit(const QString &unit)
{
    d->unit = unit;
    update();
}

QString DashBoardWidget::unit() const
{
    return d->unit;
}

void DashBoardWidget::setText(const QString &text)
{
    d->text = text;
    update();
}

QString DashBoardWidget::text() const
{
    return d->text;
}

void DashBoardWidget::setArcColor(const QColor &color)
{
    d->arcColor = color;
    update();
}

QColor DashBoardWidget::arcColor() const
{
    return d->arcColor;
}

void DashBoardWidget::setScaleColor(const QColor &color)
{
    d->scaleColor = color;
    update();
}

QColor DashBoardWidget::scaleColor() const
{
    return d->scaleColor;
}

void DashBoardWidget::setPointerColor(const QColor &color)
{
    d->pointerColor = color;
    update();
}

QColor DashBoardWidget::pointerColor() const
{
    return d->pointerColor;
}

void DashBoardWidget::setTextColor(const QColor &color)
{
    d->textColor = color;
    update();
}

QColor DashBoardWidget::textColor() const
{
    return d->textColor;
}

void DashBoardWidget::setBackgroundColor(const QColor &color)
{
    d->backgroundColor = color;
    update();
}

QColor DashBoardWidget::backgroundColor() const
{
    return d->backgroundColor;
}

void DashBoardWidget::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    // 背景
    // if (d->backgroundColor != Qt::transparent) {
    //     painter.setPen(Qt::NoPen);
    //     painter.fillRect(rect(), d->backgroundColor);
    // }

    // 平移中心
    painter.translate(width() / 2, height() / 2);

    // 圆环
    drawArc(&painter);

    // 刻度线
    drawScale(&painter);

    // 刻度值
    drawScaleNum(&painter);

    // 指示器
    drawPointer(&painter);

    // 当前值
    drawValue(&painter);
}

void DashBoardWidget::onStartAnimation(const double value)
{
    if(value < d->minValue
        || value > d->maxValue
        || value == d->value)
        return;

    int start = d->value;
    int end = value;

    d->animation->setStartValue(start);
    d->animation->setEndValue(end);
    d->animation->start();
}

double DashBoardWidget::value() const
{
    return d->value;
}

void DashBoardWidget::setValue(const double value)
{
    d->value = value;
    update();
}

//画圆弧
void DashBoardWidget::drawArc(QPainter *painter)
{
    double min = qMin(width(), height());
    double arcWidth = min / 15.0;
    double radius = min / 3 - arcWidth;
    QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);

    // 创建一个线性渐变
    QLinearGradient gradient(rect.topLeft(), rect.bottomRight());
    gradient.setColorAt(0.0, QColor(255, 0, 0)); // 起始颜色:红色
    gradient.setColorAt(1.0, QColor(0, 0, 255)); // 终止颜色:蓝色

    QPen pen;
    pen.setWidthF(arcWidth);
    pen.setCapStyle(Qt::FlatCap);

    // 设置画笔为渐变色
    QBrush brush(gradient);
    pen.setBrush(brush);

    // 圆弧背景
    double angle = d->endAngle - d->startAngle;
    painter->setPen(pen);
    painter->drawArc(rect, d->startAngle * 16, angle * 16);
}


void DashBoardWidget::drawScale(QPainter *painter)
{
    painter->save();

    painter->rotate(270 - d->endAngle);
    int steps = (d->scaleMajor * d->scaleMinor);
    double angleStep = (d->endAngle - d->startAngle) / steps;
    double min = qMin(width(), height());
    double radius = min / 3;

    QPen pen(d->scaleColor);
    pen.setCapStyle(Qt::RoundCap);

    for (int i = 0; i <= steps; i++) {
        if (i % d->scaleMinor == 0) {
            pen.setWidthF(1.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 8, 0, radius + 5);
        } else {
            pen.setWidthF(0.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 8, 0, radius - 3);
        }

        painter->rotate(angleStep);
    }

    painter->restore();
}

void DashBoardWidget::drawScaleNum(QPainter *painter)
{
    painter->save();
    painter->setPen(d->scaleColor);
    double min = qMin(width(), height());
    double radius = min / 2.4;
    QFont font("Microsoft YaHei", min / 25);
    painter->setFont(font);

    double startRad = d->endAngle * (M_PI / 180);
    double deltaRad = (d->endAngle - d->startAngle) * (M_PI / 180) / d->scaleMajor;

    QFontMetrics fontMetrics(font);
    for (int i = 0; i <= d->scaleMajor; i++) {
        double sina = qSin(startRad - i * deltaRad);
        double cosa = qCos(startRad - i * deltaRad);
        double value = 1.0 * i * ((d->maxValue - d->minValue) / d->scaleMajor) + d->minValue;

        QString strValue = QString("%1").arg(value);
        double textWidth = fontMetrics.horizontalAdvance(strValue);
        double textHeight = fontMetrics.height();
        int x = radius * cosa - textWidth / 2;
        int y = -radius * sina + textHeight / 4;
        painter->drawText(x, y, strValue);
    }

    painter->restore();
}


void DashBoardWidget::drawPointer(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(d->pointerColor);

    double radius = qMin(width(), height()) / 3.0;

    QPolygonF pts;
    pts << QPointF(-5, 0) << QPointF(0, -8)
        << QPointF(5, 0) << QPointF(0, radius);

    painter->rotate(270 - d->endAngle);
    double degRotate = (d->endAngle - d->startAngle) / (d->maxValue - d->minValue) * (d->value - d->minValue);
    painter->rotate(degRotate);
    painter->drawConvexPolygon(pts);

    painter->restore();
}


void DashBoardWidget::drawValue(QPainter *painter)
{
    painter->save();
    painter->setPen(d->textColor);

    double min = qMin(width(), height());
    double radius = min / 2.0 - min / 4.8;
    QFont font("Microsoft YaHei", min / 25);
    painter->setFont(font);

    QString strValue = QString("%1").arg(d->value);
    strValue = QString("%1 %2").arg(strValue, d->unit);
    QRectF valueRect(-radius, radius / 2.5, radius * 2, radius / 3.5);
    painter->drawText(valueRect, Qt::AlignCenter, strValue);

    QRectF textRect(-radius, radius / 1.5, radius * 2, radius / 2.5);
    //font.setPixelSize(12);
    painter->setFont(font);
    painter->drawText(textRect, Qt::AlignCenter, d->text);

    painter->restore();
}

void DashBoardWidget::setSpeed(int speed)
{
    if (speed < minValue)
        speed = minValue;
    else if (speed > maxValue)
        speed = maxValue;

    d->value = speed;
    update();
}

所有代码:https://gitee.com/wangning719/dash-board-widget

相关推荐
「QT(C++)开发工程师」2 小时前
【qt版本概述】
开发语言·qt
一路冰雨6 小时前
Qt打开文件对话框选择文件之后弹出两次
开发语言·qt
老赵的博客6 小时前
QT 自定义界面布局要诀
开发语言·qt
码码哈哈0.07 小时前
VSCode 2022 离线安装插件QT VSTOOl报错此扩展不能安装在任何当前安装的产品上。
ide·vscode·qt
理论最高的吻9 小时前
98. 验证二叉搜索树【 力扣(LeetCode) 】
数据结构·c++·算法·leetcode·职场和发展·二叉树·c
feiyangqingyun10 小时前
Qt/C++离线地图的加载和交互/可以离线使用/百度和天地图离线/支持手机上运行
c++·qt·qt天地图·qt离线地图·qt地图导航
时光の尘12 小时前
C语言菜鸟入门·关键字·void的用法
c语言·开发语言·c++·算法·c#·c·关键字
gz94561 天前
windows下,用CMake编译qt项目,出现错误By not providing “FindQt5.cmake“...
开发语言·qt
「QT(C++)开发工程师」1 天前
Ubuntu 26.04 LTS 大升级:Qt 6 成为未来新引擎
qt
兆。1 天前
python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具
爬虫·python·qt