12-Qt中使用QPainter绘制可以旋转角度的矩形

一、效果图

在这里插入图片描述

二、原理

  1. 因为QPainter只能绘制水平的矩形,而现在想要绘制旋转来一定角度的矩形,就需要使用QPainter的旋转功能了。使用到的函数分别如下:
  • painter.translate(x1, y1);//把参数(x1, y1)指定的点移动到绘图区的左上角(绘图原点),使得目标绘制坐标成为坐标系的原点(0,0)
  • painter.rotate(angle); //以坐标原点为中点,旋转参数指定角度,范围是[-180,180]
  • painter.resetTransform();//恢复translate和rotate对painter作的修改
  1. 实现绘制旋转指定角度的矩形的原理:先把坐标系从指定度数的角度旋转到0度,然后在旋转后的坐标系中画一个水平的矩形,然后在旋转回去。就实现了指定角度的矩形绘制;
  2. 举例:比如以绘图区域中心为中点,绘制一个负45度的矩形。
painter.resetTransform();先重置参数
painter.translate(this-\>width()/2, this-\>height()/2);//把画图区域中心点作为坐标系原点
painter.rotate(-45);//从目标角度逆时针旋转到0du,
QRect rect;
rect.setX(0 - radius);//注意现在虽然是从(0,0)点绘制,但实际会在translate的参数指定的位置画出
rect.setY(0 - radius);
rect.setHeight(radius*2);
rect.setWidth(distance);
painter.fillRect(rect, QBrush(QColor(146, 251, 91, 128)));//绘制矩形
painter.resetTransform();//重置参数
;//empty line
;//empty line
;//empty line

三、源代码

因为源代码很少,就直接贴在下面了
anglerectview.h

#ifndef ANGLERECTVIEW_H
#define ANGLERECTVIEW_H

#include <QWidget>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QPoint>
#include <QList>
#include <QMenu>
#include <QApplication>

class AngleRectView : public QWidget
{
    Q_OBJECT
public:
    explicit AngleRectView(QWidget *parent);
    ~AngleRectView() override;

    enum MoveDirection {
        Up,
        UpRight,
        Right,
        DownRight,
        Down,
        DownLeft,
        Left,
        UpLeft
    };
protected:
    void paintEvent(QPaintEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
private:
    double CalcDistance(const QPoint& pt1, const QPoint& pt2);
    int GetAngleOfCurrentAngleRotateToZoroAngleByDirection(int direction);
    void DrawRegionBlock(QPainter &painter, int x1, int y1, int x2, int y2,
                                           double step_width, int derection);
    int CalcMoveDirection(int x1, int y1, int x2, int y2);
private:
    QPoint mouse_current_move_pos_;
};
#endif // ANGLERECTVIEW_H
;//empty line
;//empty line

anglerectview.cpp

#include "anglerectview.h"
#include <QPainter>
#include <QtMath>
#include <qmath.h>

AngleRectView::AngleRectView(QWidget *parent)
    : QWidget(parent)
{
    setMouseTracking(true);
}

AngleRectView::~AngleRectView()
{
}

void AngleRectView::paintEvent(QPaintEvent *event) {
    Q_UNUSED(event)
    QPainter painter(this);
    //draw bg
    QRect frame_rect = this->rect();
    painter.fillRect(frame_rect, QBrush(QColor(54, 54, 54)));
    int x1 = frame_rect.width()/2;
    int y1 = frame_rect.height()/2;
    int x2 = mouse_current_move_pos_.x();
    int y2 = mouse_current_move_pos_.y();
    int derection = CalcMoveDirection(x1, y1, x2, y2);
    DrawRegionBlock(painter, x1, y1, x2, y2, 50, derection);
}

void AngleRectView::mouseMoveEvent(QMouseEvent *event) {
    Q_UNUSED(event)
    mouse_current_move_pos_ = event->pos();
    update();
}

void AngleRectView::DrawRegionBlock(QPainter &painter, int x1, int y1, int x2, int y2,
                                       double step_width, int derection) {

    int radius = qRound(step_width / 5);
    if(radius > 2) {
        int distance = static_cast<int>(CalcDistance(QPoint(x1, y1), QPoint(x2, y2)));

        distance += radius;
        QRect rect;

        painter.resetTransform();
        int angle = GetAngleOfCurrentAngleRotateToZoroAngleByDirection(derection);

        painter.translate(x1, y1);//trans 0,0 to x1, y1
        painter.rotate(angle); //rotate to angle 0

        rect.setX(0 - radius);
        rect.setY(0 - radius);
        rect.setHeight(radius*2);
        rect.setWidth(distance);
        painter.fillRect(rect, QBrush(QColor(146, 251, 91, 128)));
        //draw outline
        QPen backup_temp_pen = painter.pen();
        painter.setPen(Qt::white);
        painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());
        painter.drawLine(rect.left(), rect.bottom(), rect.right(), rect.bottom());
        painter.drawLine(rect.left(), rect.top(), rect.left(), rect.bottom());
        painter.setPen(backup_temp_pen);
        painter.resetTransform();
    }
}

double AngleRectView::CalcDistance(const QPoint& pt1, const QPoint& pt2) {
    return qSqrt(double(qPow(pt2.x() - pt1.x(), 2) + qPow(pt2.y() - pt1.y(), 2) ));
}

int AngleRectView::GetAngleOfCurrentAngleRotateToZoroAngleByDirection(int direction) {
    switch (direction) {
    case Right: { return 0;}
    case DownRight:{ return 45;}
    case Down:{ return 90; }
    case DownLeft:{ return 135; }
    case Left:{ return 180; }
    case UpLeft:{ return -135; }
    case Up:{ return -90; }
    case UpRight:{ return -45; }
    }
    return 0;
}

int AngleRectView::CalcMoveDirection(int x1, int y1, int x2, int y2) {
       double rr = qAtan2(y2 - y1, x2 - x1);
       int angle = static_cast<int>(180/M_PI * rr);
       if(angle > 0) {
           angle = 360 - angle;
       } else {
           angle = angle * -1;
       }
       if(angle >= 23 && angle < 68) {
           return UpRight;
       } else if(angle >= 68 && angle < 113) {
           return Up;
       } else if(angle >= 113 && angle < 158) {
           return UpLeft;
       } else if(angle >= 158 && angle < 203) {
           return Left;
       } else if(angle >= 203 && angle < 248) {
           return DownLeft;
       } else if(angle >= 248 && angle < 293) {
           return Down;
       } else if(angle >= 293 && angle < 338) {
           return DownRight;
       } else if((angle >= 338 && angle < 360) || 
       				(angle >= 0 && angle < 23)) {
           return Right;
       }
       return 0;
}
;//empty line
;//empty line
;//empty line
;//empty line
;//empty line
;//empty line
;//empty line
;//empty line

在QtCreater中新建窗口应用程序,在主窗口的构造函数添加如下代码

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QHBoxLayout>
#include "./views/anglerectview/anglerectview.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //以下为手工添加的布局AngleRectView控件的代码
    QHBoxLayout *center_layout = new QHBoxLayout(ui->centralwidget);
    AngleRectView *angle_rect_view = new AngleRectView(ui->centralwidget);
    angle_rect_view->setObjectName(QString::fromUtf8("angle_rect_view"));
    center_layout->addWidget(angle_rect_view);
}

MainWindow::~MainWindow()
{
    delete ui;
}
;//empty line
发布了88 篇原创文章 · 获赞 45 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/robert_cysy/article/details/102384132
今日推荐