Qt自绘圆盘图控件

本人使用QPainter自绘了一个圆盘图,下面这张图片为效果图

图片中的所有(圆、刻度线、字体)均为自绘,没有使用图片

使用方法:在Ui中拖拽一个widget控件,然后右键点击该widget控件,选择提升。

 

话不多说,直接上代码

头文件qdiscwidget.h

#ifndef QDISCWIDGET_H
#define QDISCWIDGET_H

#include <QWidget>
#include <QPainter>
#include <QPen>
#include <QMouseEvent>
#include <QtMath>
#include <QLabel>
#include <QPushButton>
#include <QVector>
#include <QMutableVectorIterator>
#include <QtDataVisualization>

class QDiscWidget : public QWidget
{
    Q_OBJECT

public:
    explicit QDiscWidget(QWidget *parent = 0);
    ~QDiscWidget();

protected:
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;
    void enterEvent(QEvent *event) override;
    void leaveEvent(QEvent *event) override;


private slots:
    void on_timeout();

private:
    int side;     //表示宽,高中较小的
    int disc_R;   //圆盘半径
    int W, H;     //控件的宽高
    bool showYellowLine;   //是否显示黄线
    bool showRedLine;       //是否显示红线
    QPointF yellowLinePoint, redLinePoint, pressPoint;   //记录移动中黄线、红线的点,以及鼠标按下的点       //表示信号的点,以及信号消失的点
    qreal point_R;    //点的半径
    int nNum;         //控制显示Label的个数
    qreal yLineAg;    //线所在的角度
    void initWidget();
    void initPara();

private:
    void draw_disc_scale(QPainter &p);
    void draw_disc_text(QPainter &p);
    void draw_line_scale(QPainter &p);
    void draw_arc(QPainter &p);
    void fill_Gradient_color(QPainter &p);
    void draw_moveable_yline(QPainter &p);
    void draw_moveable_rline(QPainter &p);
    void draw_press_line(QPainter &p);

signals:
    void showAngle(qreal dieangle, qreal elvangle);

};

#endif // QDISCWIDGET_H

 源文件qdiscwidget.cpp

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
#include "qdiscwidget.h"


QDiscWidget::QDiscWidget(QWidget *parent) : QWidget(parent)

{
    initWidget();
    initPara();
    QTimer *timer = new QTimer(this);
    timer->start(50);
    connect(timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
}

QDiscWidget::~QDiscWidget()
{

}

//初始化控件
void QDiscWidget::initWidget()
{

    setPalette(QPalette(QColor(13, 46, 62)));//设置背景色
//    setPalette(QPalette(QColor(0, 0, 0)));
    setAutoFillBackground(true);
    setMouseTracking(true);

}

//初始化参数
void QDiscWidget::initPara()
{

    disc_R = 93;
    point_R = 0.8;
    showYellowLine = true;
    showRedLine = false;
}

void QDiscWidget::paintEvent(QPaintEvent *event)
{

    //side = (width() > height()) ? height() : width();
    side = qMin(W, H);
    QPainter painter(this);
    QRect rect((W-side)/2, (H-side)/2, side, side);
    painter.setViewport(rect);
    painter.setWindow(-100, -100, 200, 200);
    painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing);  // 启用反锯齿

    draw_disc_scale(painter);
    draw_disc_text(painter);
    draw_line_scale(painter);
    draw_arc(painter);
    fill_Gradient_color(painter);
    draw_moveable_yline(painter);
    draw_moveable_rline(painter);
    draw_press_line(painter);
}

void QDiscWidget::mousePressEvent(QMouseEvent * event)
{
    qreal pointX = event->x() - W / 2;
    qreal pointY = event->y() - H / 2;
    if(showRedLine && !showYellowLine)
    {
        showRedLine = false;
        return;
    }
    if(showYellowLine && !showRedLine && !redLinePoint.isNull())
    {
        showYellowLine = false;
        return;
    }
    if(showYellowLine && !showRedLine)
    {
        //将按下的点的坐标转换为圆上的点(即距离圆心为半径)
        pressPoint = QPointF(pointX * disc_R / qSqrt(pointX * pointX + pointY * pointY), pointY * disc_R / qSqrt(pointX * pointX + pointY * pointY));

    }
    //当黄线和红线都不能移动时,判断目前按下的点距离哪条线更近一点,并让其可移动
    if(!showRedLine && !showYellowLine)
    {
        QPointF point = QPointF(pointX * disc_R / qSqrt(pointX * pointX + pointY * pointY), pointY * disc_R / qSqrt(pointX * pointX + pointY * pointY));
        qreal dst1 = qPow((point.x() - yellowLinePoint.x()),2) + qPow((point.y() - yellowLinePoint.y()),2);
        qreal dst2 = qPow((point.x() - redLinePoint.x()),2) + qPow((point.y() - redLinePoint.y()),2);
        if(dst1<dst2)
        {
            showYellowLine = true;
        }
        if(dst1>dst2)
        {
            showRedLine = true;
        }
    }

}

void QDiscWidget::enterEvent(QEvent *event)
{
//    QWidget::enterEvent(event);
    //设置鼠标的形状为十字星
    setCursor(Qt::CrossCursor);
}

void QDiscWidget::leaveEvent(QEvent *event)
{
    //恢复鼠标的形状
    setCursor(Qt::CustomCursor);
    QWidget::leaveEvent(event);
}

void QDiscWidget::mouseMoveEvent(QMouseEvent * event)
{
    qreal pointX = event->x() - W / 2;
    qreal pointY = event->y() - H / 2;
    //计算出当前可移动的线所在的角度(0~360)
    yLineAg = qAsin(pointX/qSqrt(pointX * pointX + pointY * pointY))*180/3.1415;
    if(pointY>=0)
    {
        yLineAg = 180-yLineAg;
    }
    if(pointX<0 && pointY<0)
    {
        yLineAg += 360;
    }
}

void QDiscWidget::mouseReleaseEvent(QMouseEvent * event)
{

}

//绘制圆盘的刻度
void QDiscWidget::draw_disc_scale(QPainter &p)
{
    p.save();
    QPen pen(QColor(255, 255, 255));
    pen.setWidth(0.5);
    p.setPen(pen);
    for (int i = 0; i < 360; ++i)
    {
        if ((i % 10) == 0)
        {
            if ((i % 3) == 0)
            {
                p.drawLine(0, 0, disc_R, 0);
            }
            p.drawLine(disc_R - 4, 0, disc_R, 0);
        }
        else
        {
            p.drawLine(disc_R - 2, 0, disc_R, 0);
        }
        p.rotate(1);
    }
    p.restore();
}

//绘制刻度所对应的字体
void QDiscWidget::draw_disc_text(QPainter &p)
{
    p.save();
    QString text;
    QPen pen(QColor(255, 255, 255));
    pen.setWidth(0.5);
    p.setPen(pen);
    QFont font("Microsoft YaHei", 2);
    p.setFont(font);
    int pointsize = font.pointSize();
    int radius = 100;
    float width = pointsize * 3;
    float height = pointsize * 2;

    for(int i = 0; i < 36; ++i)
    {
        double y = -(double)radius * 0.97 * qCos(i *  M_PI/ 18.0) -1.5;
        double x = -(double)radius * 0.97 * qSin(i * M_PI / 18.0) -2.5;
        if (i == 0)
        {
            text = "0";
        }
        else
        {
            text = text.sprintf("%d", (360 - 10 * i));
        }
        p.drawText(QRectF(x, y, width, height), Qt::AlignCenter, text);
    }
    p.restore();
}

// 画圆内垂直线上半段的刻度以及字体
void QDiscWidget::draw_line_scale(QPainter &p)
{
    float h;
    QString strText;
    QPen pen(QColor(255, 0, 0));
    pen.setWidth(0.5);
    QFont font("Microsoft YaHei", 3);
    p.save();
    p.setPen(pen);
    p.setFont(font);
    for (int i = 1; i < 9; ++i)
    {
        h = double(-disc_R) / 9.0 * (9-i);
        p.drawLine(0, h, 3, h);
        p.drawText(QPoint(-5, h), strText.sprintf("%d", (10*i)));
    }
    p.restore();
}

//画两个内圆
void QDiscWidget::draw_arc(QPainter &p)
{
    p.save();
    QPen pen(QColor(255, 255, 255));
    pen.setWidth(0.5);
    p.setPen(pen);
    float r = float(disc_R) / 9 * 3;
    float r1 = r * 2;
    p.drawEllipse(QRect(QPoint(-r, -r), QPoint(r, r)));
    p.drawEllipse(QRect(QPoint(-r1, -r1), QPoint(r1, r1)));
    p.restore();
}

//给圆盘填充颜色
void QDiscWidget::fill_Gradient_color(QPainter & p)
{
    p.save();
    QPen pen(QColor(255, 255, 255));
    pen.setWidth(0.5);
    p.setPen(pen);
    //辐射渐变
    //QRadialGradient radialgrad(QPointF(0, 0), disc_R);
//    QRadialGradient radialgrad(0, 0, disc_R/2, 0, 0);
//    radialgrad.setColorAt(0, QColor(0, 0, 100, 150));
//    radialgrad.setColorAt(0.5, QColor(170, 0, 200, 150));
//    radialgrad.setColorAt(1, QColor(0, 0, 100, 150));
//    radialgrad.setSpread(QGradient::ReflectSpread);
    //线性渐变
    /*QLinearGradient linegrad(QPointF(-90, 10), QPointF(90, 10));
    linegrad.setColorAt(0, QColor(0, 0, 100, 150));
    linegrad.setColorAt(0.5, QColor(170, 0, 200, 150));
    linegrad.setColorAt(1, QColor(0, 0, 100, 150));
    linegrad.setSpread(QGradient::RepeatSpread);*/
    p.setBrush(QColor(10, 0, 5, 150));
    p.drawEllipse(QRect(QPoint(-disc_R, -disc_R), QPoint(disc_R, disc_R)));
    p.restore();
}

//绘制可移动的黄线
void QDiscWidget::draw_moveable_yline(QPainter &p)
{
    if(yellowLinePoint.isNull())
        return;
    p.save();
    QPen pen(Qt::yellow);
    pen.setWidth(0.5);
    p.setPen(pen);
    p.drawLine(QPoint(0, 0), yellowLinePoint);
    p.restore();

}

//绘制黄线移动时,鼠标按下去所显示的线
void QDiscWidget::draw_press_line(QPainter &p)
{
    if(pressPoint.isNull() || showRedLine)
        return;
    p.save();
    QPen pen(QColor(85, 170, 255));
    pen.setWidth(0.5);
    p.setPen(pen);
    p.drawLine(QPoint(0, 0), pressPoint);
    p.restore();
}

//绘制可移动的红线
void QDiscWidget::draw_moveable_rline(QPainter &p)
{
    if(redLinePoint.isNull())
        return;
    p.save();
    QPen pen(Qt::red);
    pen.setWidth(0.5);
    p.setPen(pen);
    p.drawLine(QPoint(0, 0), redLinePoint);
    p.restore();

}

void QDiscWidget::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    W = width();
    H = height();
}

void QDiscWidget::on_timeout()
{
    update();
}

下面的这张图片是本人自己添加的一些功能

 

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的GUI(形用户界面)和功能组件,其中包括自绘控件自绘控件是指通过重写绘制函数来实现自定义外观和行为的控件。 在Qt中,自绘控件通常是从QWidget类派生而来的子类。要使用自绘控件,你需要重写QWidget的paintEvent()函数,并在其中进行绘制操作。paintEvent()函数会在控件需要重新绘制时被调用,你可以在该函数中使用Qt提供的绘工具进行绘制。 以下是使用paintEvent()函数自绘控件的基本步骤: 1. 创建一个继承自QWidget的子类,并重写其paintEvent()函数。 2. 在paintEvent()函数中,创建一个QPainter对象,并使用该对象进行绘制操作。 3. 使用QPainter提供的绘函数(如drawRect()、drawText()等)来实现你想要的外观效果。 4. 根据需要,可以在其他事件处理函数中添加交互逻辑,例如鼠标点击事件等。 下面是一个简单的示例代码,展示了如何使用paintEvent()函数自绘一个简单的矩形控件: ```cpp #include <QtWidgets> class MyWidget : public QWidget { public: MyWidget(QWidget *parent = nullptr) : QWidget(parent) {} protected: void paintEvent(QPaintEvent *event) override { Q_UNUSED(event); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 设置抗锯齿 painter.fillRect(rect(), Qt::blue); // 绘制蓝色背景 painter.setPen(Qt::white); // 设置画笔颜色为白色 painter.drawRect(rect().adjusted(10, 10, -10, -10)); // 绘制带边距的矩形 } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); MyWidget widget; widget.resize(200, 200); widget.show(); return app.exec(); } ``` 这个示例中,我们创建了一个名为MyWidget的自定义控件,重写了其paintEvent()函数,在其中使用QPainter对象绘制了一个带有蓝色背景和白色边框的矩形。在main()函数中,我们创建了一个应用程序对象,并显示了这个自定义控件

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值