C++/QT绘画 绘制两圆上之间的箭头

目录

一、绘制两圆上箭头,即从两圆心连线与圆上的交点画箭头。

二、上代码

三、在QT中画出这两个圆和箭头

四、实现移动这个带文字的圆并且箭头跟随

五、源码

一、绘制两圆上箭头,即从两圆心连线与圆上的交点画箭头。

        首先得到根据圆心得到圆上坐标

        再根据圆上坐标画出箭头

二、上代码

/*
 * 首先根据圆心求出两点间距离l
 * r/l根据等比三角形求出圆心连线在圆上的点坐标(有兴趣可以画图分析)
*/
void cutLineLength(QPoint p1,QPoint p2,QPoint &p3,QPoint &p4,int r)
{
    double dDist=0,dDeta=0;
    double dPX,dPY,dP1X,dP1Y,dP2X,dP2Y;

    dPX = p1.x() - p2.x();
    dPY = p1.y() - p2.y();

    dDist = sqrt(dPX*dPX +dPY*dPY);
    dDeta = r / dDist;

    dP1X = p1.x() - (dPX)*dDeta;
    dP1Y = p1.y() - (dPY)*dDeta;

    dP2X = p2.x() + dPX*dDeta;
    dP2Y = p2.y() + dPY*dDeta;

    p3.setX(dP1X);
    p3.setY(dP1Y);
    p4.setX(dP2X);
    p4.setY(dP2Y);
}

//说白了箭头就是四个点组成的。上面的函数得到了两个圆上坐标,
//选取其中一个点作为箭头点(这里的p2)得到p2两边的坐标p3,p4。

void calArrowPoint(QPoint p1,QPoint p2,QPoint& p3,QPoint& p4)
{
    double arrowLength = 10;
    double arrowDegrees = 0.5;

    //求p1和p2之间的角度
    double angle = atan2(p2.y()-p1.y(),p2.x()-p1.x());

    p3.setX(p2.x() - arrowLength * cos(angle - arrowDegrees));
    p3.setY(p2.y() - arrowLength * sin(angle - arrowDegrees));

    p4.setX(p2.x() - arrowLength * cos(angle + arrowDegrees));
    p4.setY(p2.y() - arrowLength * sin(angle + arrowDegrees));
}

三、在QT中画出这两个圆和箭头

在头文件中重在paintEvent函数和两个点坐标,并实现重绘。

 .h                     

protected:
    void paintEvent(QPaintEvent *event) override;
private:
    QPoint fastPoint;
    QPoint lastPoint;
    int    r = 50;

.cpp       

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QString str = "hello world";
    QString drawStr;
    if(str.length() > 3)
    {
        drawStr = str.mid(0,2);
        drawStr.append("...");
    }

    QFont font;
    painter.save();
    font = painter.font();
    font.setPointSize(12);
    painter.setFont(font);
    painter.setBrush(QBrush(QColor(200,200,100)));

    painter.drawEllipse(fastPoint,r,r);//原点为fastPoint,半径为50
    painter.drawEllipse(lastPoint,r,r);
    painter.drawText(fastPoint.x()-r,fastPoint.y()-r,2*r,2*r,
                     Qt::AlignHCenter | Qt::AlignVCenter,str);
    //painter.drawLine(fastPoint,lastPoint);
    painter.restore();
    QPoint p1,p2,p3,p4;
    cutLineLength(fastPoint,lastPoint,p1,p2,r/2);
    calArrowPoint(p1,p2,p3,p4);
    painter.drawLine(p1,p2);
    painter.drawLine(p2,p3);
    painter.drawLine(p2,p4);
}

 到这里就可以画出来两个圆和箭头了

四、实现移动这个带文字的圆并且箭头跟随

.h 增加鼠标按下、移动、释放事件        

protected:
    void mouseMoveEvent(QMouseEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void paintEvent(QPaintEvent *event) override;
private:
    Ui::MainWindow *ui;
    bool pushButton = false;
    QPoint fastPoint;
    QPoint lastPoint;
    QPoint movePoint;
    int r = 50;

 .cpp 中处理事件

//鼠标移动事件
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    QPoint p = event->pos();
    if(pushButton)
    {
        fastPoint.setX(p.x() + movePoint.x());
        fastPoint.setY(p.y() + movePoint.y());
        update();
    }
}
//鼠标按下
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    QPoint p = event->pos();
    if(event->button() == Qt::LeftButton && p.x() > fastPoint.x()-r/2 &&
        p.x() <fastPoint.x()+r/2 && p.y() > fastPoint.y() -r/2
        && p.y() < fastPoint.y() + r/2)
    {
        pushButton = true;
        movePoint.setX(fastPoint.x() - p.x());
        movePoint.setY(fastPoint.y() - p.y());
    }
}
//鼠标释放
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        pushButton = false;
}

五、源码

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void mouseMoveEvent(QMouseEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

private:
    Ui::MainWindow *ui;
    bool pushButton = false;
    QPoint fastPoint;
    QPoint lastPoint;
    QPoint movePoint;
    int r = 50;
};
#endif // MAINWINDOW_H

.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QDebug>
#include <QFile>
#include <QMouseEvent>
#include <math.h>
/*
 * 画两个圆之间的箭头(圆上)
 * 首先根据圆心求出两点间距离l
 * r/l根据勾股定理求出圆心连线在圆上的点坐标(自己分析)
 * 根据圆上坐标画箭头p3->p4
*/
void cutLineLength(QPoint p1,QPoint p2,QPoint &p3,QPoint &p4,int r)
{
    double dDist=0,dDeta=0;
    double dPX,dPY,dP1X,dP1Y,dP2X,dP2Y;

    dPX = p1.x() - p2.x();
    dPY = p1.y() - p2.y();

    dDist = sqrt(dPX*dPX +dPY*dPY);
    dDeta = r / dDist;

    dP1X = p1.x() - (dPX)*dDeta;
    dP1Y = p1.y() - (dPY)*dDeta;

    dP2X = p2.x() + dPX*dDeta;
    dP2Y = p2.y() + dPY*dDeta;

    p3.setX(dP1X);
    p3.setY(dP1Y);
    p4.setX(dP2X);
    p4.setY(dP2Y);
}

void calArrowPoint(QPoint p1,QPoint p2,QPoint& p3,QPoint& p4)
{
    double arrowLength = 10;
    double arrowDegrees = 0.5;

    //求p1和p2之间的角度
    double angle = atan2(p2.y()-p1.y(),p2.x()-p1.x());

    p3.setX(p2.x() - arrowLength * cos(angle - arrowDegrees));
    p3.setY(p2.y() - arrowLength * sin(angle - arrowDegrees));

    p4.setX(p2.x() - arrowLength * cos(angle + arrowDegrees));
    p4.setY(p2.y() - arrowLength * sin(angle + arrowDegrees));
}

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

    fastPoint = QPoint(50,50);
    lastPoint = QPoint(200,200);
}

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




void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QString str = "hello world";
    QString drawStr;
    if(str.length() > 3)
    {
        drawStr = str.mid(0,2);
        drawStr.append("...");
    }


    painter.setRenderHint(QPainter::Antialiasing);
    /*
     * translate改变坐标系,将原点坐标改到屏幕中央
     *side是窗口最小的那个边长
     *200是缩放的比例,当side/200达到1、2、3...n时就会进行缩放
     *也就是说当最小边长为200、400、600、800时会进行1、2、3、4倍的放大
    */
    //int side = qMin(width(),height());
    //painter.translate(width()/2,height()/2);
    //painter.scale(side/ 200 , side / 200);

    QFont font;
    painter.save();
    font = painter.font();
    font.setPointSize(12);
    painter.setFont(font);
    painter.setBrush(QBrush(QColor(200,200,100)));

    painter.drawEllipse(fastPoint,r/2,r/2);//原点为fastPoint,半径为50
    painter.drawEllipse(lastPoint,r/2,r/2);
    painter.drawText(fastPoint.x()-r/2,fastPoint.y()-r/2,r,r,
                     Qt::AlignHCenter | Qt::AlignVCenter,str);
    //painter.drawLine(fastPoint,lastPoint);
    painter.restore();
    QPoint p1,p2,p3,p4;
    cutLineLength(fastPoint,lastPoint,p1,p2,r/2);
    calArrowPoint(p1,p2,p3,p4);
    painter.drawLine(p1,p2);
    painter.drawLine(p2,p3);
    painter.drawLine(p2,p4);
}




//鼠标移动事件
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    QPoint p = event->pos();
    if(pushButton)
    {
        fastPoint.setX(p.x() + movePoint.x());
        fastPoint.setY(p.y() + movePoint.y());
        update();
    }
}
//鼠标按下
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    QPoint p = event->pos();
    if(event->button() == Qt::LeftButton && p.x() > fastPoint.x()-r/2 &&
        p.x() <fastPoint.x()+r/2 && p.y() > fastPoint.y() -r/2
        && p.y() < fastPoint.y() + r/2)
    {
        pushButton = true;
        movePoint.setX(fastPoint.x() - p.x());
        movePoint.setY(fastPoint.y() - p.y());
    }
}
//鼠标释放
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        pushButton = false;
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值