绘画系统(101):【例】量角器

本文介绍了一个使用Qt库创建的自定义量角器控件。该控件通过两个滑块来调整红色和绿色指针的角度,并实时更新在半圆形的量角器上。通过信号槽机制实现了滑块与量角器之间的互动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

main.cpp

#include <QtWidgets>
#include "Widget.h"

int main(int argc, char *argv[])
{
    QApplication app(argc,argv);

    Widget w;
    w.show();

    return app.exec();
}

Widget类

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QtWidgets>
#include "Protractor.h"

class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = nullptr);

protected:

signals:
private:
    QSpinBox *greenSpin;
    QSpinBox *redSpin;
    Protractor *protractor;
    int radius;

};

#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent)
{
    redSpin   = new QSpinBox(this);     // 红色微调框
    redSpin->setRange(0,180);

    greenSpin = new QSpinBox(this);     // 绿色微调框
    greenSpin->setRange(0,180);

    QSlider *redSlider = new QSlider(Qt::Horizontal,this);  // 红色滑块
    redSlider->setRange(0,180);

    connect(redSlider,&QSlider::valueChanged, redSpin,  &QSpinBox::setValue);
    connect(redSpin,  QOverload<int>::of(&QSpinBox::valueChanged),redSlider,&QSlider::setValue);

    QSlider *greenSlider = new QSlider(Qt::Horizontal,this);// 绿色滑块
    greenSlider->setRange(0,180);
    connect(greenSlider,&QSlider::valueChanged, greenSpin,  &QSpinBox::setValue);
    connect(greenSpin,  QOverload<int>::of(&QSpinBox::valueChanged),greenSlider,&QSlider::setValue);

    protractor = new Protractor(this);      // 量角器控件
    connect(redSlider,&QSlider::valueChanged, protractor,  &Protractor::redChanged);
    connect(greenSlider,&QSlider::valueChanged, protractor,  &Protractor::greenChanged);

    QGridLayout *mainLayout = new QGridLayout(this);
    mainLayout->addWidget(protractor,0,0,1,3);
    QLabel *redLabel = new QLabel("红色指针");
    redLabel->setAlignment(Qt::AlignCenter);
    mainLayout->addWidget(redLabel ,1,0);
    mainLayout->addWidget(redSlider,1,1);
    mainLayout->addWidget(redSpin  ,1,2);

    QLabel *greenLabel = new QLabel("绿色指针");
    greenLabel->setAlignment(Qt::AlignCenter);

    mainLayout->addWidget(greenLabel,2,0);
    mainLayout->addWidget(greenSlider,2,1);
    mainLayout->addWidget(greenSpin  ,2,2);

    mainLayout->setColumnStretch(0,2);
    mainLayout->setColumnStretch(1,1);
    mainLayout->setColumnStretch(2,0);

    redSlider->setValue(70);
    greenSlider->setValue(130);
}

Protractor类

Protractor.h

#ifndef PROTRACTOR_H
#define PROTRACTOR_H

#include <QWidget>


class Protractor : public QWidget
{
    Q_OBJECT
public:
    explicit Protractor(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *event) override;

public slots:
    void redChanged(int red);
    void greenChanged(int green);

signals:
private:
    int m_red = 0;
    int m_green = 0;
};

#endif // PROTRACTOR_H

Protractor.cpp

#include "Protractor.h"
#include <QPainter>

Protractor::Protractor(QWidget *parent) : QWidget(parent)
{
    this->setMinimumSize(800,400);  // 设置最小大小
}

void Protractor::paintEvent(QPaintEvent */*event*/)
{
    QPainter painter(this);  // 画家
    painter.fillRect(this->rect(),Qt::black);  // 背景色
    painter.setRenderHints(QPainter::Antialiasing);  // 抗锯齿
    qreal raduis = width()/2.0;     // 半圆的半径
    painter.setPen(QPen(Qt::white,2));   // 画笔颜色
    QPointF zero(width()/2,height()-10);    // 圆心
    painter.drawEllipse(zero,raduis * 0.8,raduis *0.8); // 画圆
    painter.drawEllipse(zero,raduis * 0.6,raduis *0.6); // 画圆

    painter.translate(zero);    // 平移到圆心
    painter.save();

    QFontMetrics fm = this->fontMetrics();  // 字体的量度

    for (int i = 0; i <= 180; ++i) {
        if(i % 30 == 0){    // 每30度 画一条虚线
            painter.save();
            painter.setPen(QPen(QColor(255,255,255,120),2,Qt::DashDotDotLine));
            painter.drawLine( 0, 0, raduis * 0.8, 0 );
            painter.restore();
        }

        if(i % 10 == 0) {   // 每10度 画一条长刻度  标识角度
            painter.drawLine( raduis * 0.8 ,0 , raduis * 0.8 - 20, 0 );
            painter.drawLine( raduis * 0.6 ,0 , raduis * 0.6 - 20, 0 );
            painter.save();

            QString temp = QString("%1度").arg(i);
            int tw = fm.horizontalAdvance(temp);
            int th = fm.height();
            painter.translate(raduis * 0.8 + tw/2+10, 0);

            painter.rotate(i);
            painter.drawText(-tw/2,th/2,QString("%1度").arg(i));
            painter.restore();
        }
        else {      // 短刻度
            painter.drawLine( raduis * 0.8 ,0 , raduis * 0.8 - 10, 0 );
            painter.drawLine( raduis * 0.6 ,0 , raduis * 0.6 - 10, 0 );
        }
        painter.rotate(-1); // 逆时针旋转1度,
    }
    painter.restore();

    painter.save();
    painter.rotate(-m_red);             // 红色指针
    painter.setPen(QPen(Qt::red,2));
    painter.drawLine(0,0, raduis * 0.8 + 10, 0);
    painter.restore();

    painter.save();
    painter.rotate(- m_green);          // 绿色指针
    painter.setPen(QPen(Qt::green,2));
    painter.drawLine(0,0, raduis * 0.6 + 10, 0);
    painter.restore();

}

void Protractor::redChanged(int red)    // 红色指针的刻度变换
{
    m_red = red;        // 赋给成员变量
    update();
}

void Protractor::greenChanged(int green) // 绿色指针的刻度变换
{
    m_green = green;    // 赋给成员变量
    update();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值