Qt编写自定义控件:遥控器圆形按钮控件

根据QT图形视图框架:自定义遥控器圆形按钮图形项改的QWidget版本,原理一样。

效果:

代码:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    void selectColor(QString colorString);
protected:
    void paintEvent(QPaintEvent *event)override;
    void mousePressEvent(QMouseEvent *event)override;
    void mouseReleaseEvent(QMouseEvent* event)override;
private:
    Ui::Widget *ui;
    bool isPointInCir(const QPoint &point, const QRect &rect);
    QRectF drawRect;//整个大圆的范围
    QPainterPath fanShaped[4];
    QRectF centerCircularRect;//中心圆按钮的范围
    QPainterPath gradientArc(double startAngle, double angleLength, double arcHeight);
    enum class pressBtnType //按下的是哪个按钮
    {
        up = 0,
        left,
        down,
        right,
        center,
        None
    };
    pressBtnType pressedBtn{pressBtnType::None};
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QMouseEvent>
#include <math.h>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        QPoint point = event->pos();
        if(isPointInCir(point,drawRect.toRect()))
        {
            if(isPointInCir(point,centerCircularRect.toRect()))
            {
                pressedBtn = pressBtnType::center;
            }
            else
            {
                QPoint centerPoint = drawRect.toRect().center();
                double angle = atan2(point.y()-centerPoint.y(),point.x()-centerPoint.x()); //两点之间的角度(弧度)
                angle = -angle*(180 / 3.1415926); //0°~180° - -180°~0°
                if(angle < 0.0)
                {
                    angle = 360.0 - abs(angle);
                }
                if(angle < 45.0 || angle > 315.0)
                {
                    pressedBtn = pressBtnType::right;
                }
                else if(angle >= 45.0 && angle < 135.0)
                {
                    pressedBtn = pressBtnType::up;
                }
                else if(angle >= 135.0 && angle < 225.0)
                {
                    pressedBtn = pressBtnType::left;
                }
                else if(angle >= 225.0 && angle < 315.0)
                {
                    pressedBtn = pressBtnType::down;
                }
            }
            update();
        }
    }
    return QWidget::mousePressEvent(event);
}

void Widget::mouseReleaseEvent(QMouseEvent* event)
{
    if(pressedBtn != pressBtnType::None)
    {
        pressedBtn = pressBtnType::None;
        update();
    }
    return QWidget::mouseReleaseEvent(event);
}

QPainterPath Widget::gradientArc(double startAngle, double angleLength, double arcHeight)
{
    QPainterPath path;
    path.moveTo(drawRect.center());
    path.arcTo(drawRect, startAngle, angleLength);

    QPainterPath subPath;
    subPath.addEllipse(drawRect.adjusted(arcHeight, arcHeight, -arcHeight, -arcHeight));

    // path为扇形 subPath为椭圆
    path -= subPath;
    return path;
}

void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setPen(Qt::NoPen);

    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform,true);

    QPoint centerPoint = rect().center();

    painter.save();
    painter.setPen(QColor("#222222"));
    painter.setBrush(QColor("#EAEAEA"));
    double radius = (std::min(width(),height()) - 10 * 2 ) / 2;
    drawRect = QRectF(centerPoint.x()-radius, centerPoint.y()-radius, radius*2, radius*2);
    double arcHeight = radius / 2;

    fanShaped[0] = gradientArc(45.0,  90.0, arcHeight);//上
    fanShaped[1] = gradientArc(135.0, 90.0, arcHeight);//左
    fanShaped[2] = gradientArc(225.0, 90.0, arcHeight);//下
    fanShaped[3] = gradientArc(315.0, 90.0, arcHeight);//右

    for (int i = 0;i < 4;++i)
    {
        painter.drawPath(fanShaped[i]);
    }
    painter.restore();

    centerCircularRect = QRectF(centerPoint.x() - (radius / 2), centerPoint.y() - (radius / 2), radius, radius).adjusted(2,2,-2,-2);
    painter.save();
    painter.setPen(Qt::transparent);
    painter.setBrush(QColor("#EAEAEA"));
    painter.drawEllipse(centerCircularRect);
    painter.restore();

    //绘制文字
    //左
    painter.save();
    QRectF textRect = QRectF(drawRect.x(),centerCircularRect.y(),radius / 2,radius);
    QPen p(Qt::SolidLine);
    p.setColor("#000000");
    p.setWidth(2);
    painter.setPen(p);
    QFont font = painter.font();
    font.setPixelSize(24);
    painter.setFont(font);
    painter.drawText(textRect, Qt::AlignCenter, "〈");//在此区域的中间位置绘制文字 〉

    //上
    textRect = QRectF(centerCircularRect.x(),drawRect.y(),radius,radius / 2);
    painter.drawText(textRect, Qt::AlignCenter, "︿");

    //右
    textRect = QRectF(centerCircularRect.topRight().x(),centerCircularRect.topRight().y(),radius / 2,radius);
    painter.drawText(textRect, Qt::AlignCenter, "〉");

    //下
    textRect = QRectF(centerCircularRect.bottomLeft().x(),centerCircularRect.bottomLeft().y(),radius,radius / 2);
    painter.drawText(textRect, Qt::AlignCenter, "﹀");

    painter.drawText(centerCircularRect, Qt::AlignCenter, "OK");
    painter.restore();

    if(pressedBtn != pressBtnType::None)
    {
        painter.save();
        QColor slightlyOpaqueBlack(0, 0, 0, 63);
        painter.setBrush(slightlyOpaqueBlack);
        painter.setPen(Qt::transparent);
        if(pressedBtn == pressBtnType::center)
        {
            painter.drawEllipse(centerCircularRect);
        }
        else
        {
            int index = -1;
            index = static_cast<int>(pressedBtn);
            if(index >= 0)
            {
                painter.drawPath(fanShaped[index]);
            }
        }
        painter.restore();
    }

    painter.restore();
}

bool Widget::isPointInCir(const QPoint &point,const QRect & rect)//判断点是否在圆范围内
{
    const QPoint & centerPoint = rect.center();
    int x = point.x() - centerPoint.x();
    int y = point.y() - centerPoint.y();
    if(sqrt(pow(x,2) + pow(y,2)) <= static_cast<double>(rect.width() / 2))
    {
        return true;
    }
    return false;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值