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

相关推荐
锦亦之22339 小时前
QT+OSG+OSG-earth如何在窗口显示一个地球
开发语言·qt
柳鲲鹏12 小时前
编译成功!QT/6.7.2/Creator编译Windows64 MySQL驱动(MinGW版)
开发语言·qt·mysql
三玖诶12 小时前
如何在 Qt 的 QListWidget 中逐行添加和显示数据
开发语言·qt
阳光开朗_大男孩儿18 小时前
DBUS属性原理
linux·服务器·前端·数据库·qt
Alphapeople20 小时前
Qt Modbus
开发语言·qt
竹林海中敲代码20 小时前
Qt Creator 集成开发环境 常见问题
qt·qt工具常见问题
竹林海中敲代码1 天前
Qt安卓开发连接手机调试(红米K60为例)
android·qt·智能手机
长沙红胖子Qt1 天前
关于 Qt运行加载内存较大崩溃添加扩大运行内存 的解决方法
开发语言·qt·qt扩大运行内存
gopher95111 天前
qt相关面试题
开发语言·qt·面试
三玖诶1 天前
在 Qt 中使用 QLabel 设置 GIF 动态背景
开发语言·qt·命令模式