QT 绘制贝塞尔曲线之二

137 篇文章 44 订阅

上一篇文章讲到了可以利用QT绘制一条贝塞尔曲线,但是如果绘制多条呢?
先看一下示例:
在这里插入图片描述
单条曲线定义:

#pragma once

class QPoint;
class QRect;
class QLine;

class BezierPoint {
public:
	BezierPoint();
	~BezierPoint();

	void setStartPoint(QPoint* pt);
	void setStartPoint(QPoint pt);
	QPoint* getStartPoint() {
		return _startPoint;
	}

	void setC1Point(QPoint* pt);
	void setC1Point(QPoint pt);
	QPoint* getC1Point() {
		return _c1;
	}

	void setC2Point(QPoint* pt);
	void setC2Point(QPoint pt);
	QPoint* getC2Point() {
		return _c2;
	}

	void setEndPoint(QPoint* pt);
	void setEndPoint(QPoint pt);
	QPoint* getEndPoint() {
		return _endPoint;
	}

private:
	QPoint* _startPoint = nullptr;//起始点
	QPoint* _c1 = nullptr;//第一个控制点
	QPoint* _c2 = nullptr;//第二个控制点
	QPoint* _endPoint = nullptr;//终点
}; 
#include "BezierPoint.h"
#include <QPoint>
#include <QRect>
#include <QLine>

BezierPoint::BezierPoint() {
	_startPoint = new QPoint;//起始点
	_c1 = new QPoint;//第一个控制点
	_c2 = new QPoint;//第二个控制点
	_endPoint = new QPoint;//终点
}

BezierPoint::~BezierPoint() {
}

void BezierPoint::setStartPoint(QPoint* pt) {
	_startPoint->setX(pt->x());
	_startPoint->setY(pt->y());
}

void BezierPoint::setStartPoint(QPoint pt) {
	_startPoint->setX(pt.x());
	_startPoint->setY(pt.y());

}

void BezierPoint::setC1Point(QPoint* pt) {
	_c1->setX(pt->x());
	_c1->setY(pt->y());

}

void BezierPoint::setC1Point(QPoint pt) {
	_c1->setX(pt.x());
	_c1->setY(pt.y());

}

void BezierPoint::setC2Point(QPoint* pt) {
	_c2->setX(pt->x());
	_c2->setY(pt->y());

}

void BezierPoint::setC2Point(QPoint pt) {
	_c2->setX(pt.x());
	_c2->setY(pt.y());
}

void BezierPoint::setEndPoint(QPoint* pt) {
	_endPoint->setX(pt->x());
	_endPoint->setY(pt->y());

}

void BezierPoint::setEndPoint(QPoint pt) {
	_endPoint->setX(pt.x());
	_endPoint->setY(pt.y());
} 

多条曲线定义:

#pragma once
#include <QPoint>
#include <QLine>
#include <QPainterPath>
#include <QVector>

class BezierPoint;

//贝塞尔曲线

class BezierCurves {
public:
	BezierCurves();
	~BezierCurves();

	void setStartPoint(QPoint startPoint);
	
	bool&hasStartPoint() {
		return _hasStartPoint;
	}

	QPoint&getTheStartPoint() {
		return _theStartPoint;
	}

	void setNextPoint(QPoint pt);

	QPainterPath getPath();

	QVector<BezierPoint*>&getBezierPoint() {
		return _bizerList;
	}

	void clearData();
private:
	bool _hasStartPoint = false;//是否有起点

	QPoint _theStartPoint;//单条路径的起始点 -  为了计算控制点使用

	QVector<BezierPoint*> _bizerList;//贝塞尔曲线列表

}; 
#include "BezierCurves.h"
#include "BezierPoint.h"

BezierCurves::BezierCurves() {
}

BezierCurves::~BezierCurves() {
}

void BezierCurves::setStartPoint(QPoint startPoint) {
	_hasStartPoint = true; 
	_theStartPoint = startPoint;
}

void BezierCurves::setNextPoint(QPoint pt) {
	BezierPoint* bezier = new BezierPoint;
	bezier->setStartPoint(_theStartPoint);
	bezier->setEndPoint(pt) ;
	bezier->setC1Point(QPoint((_theStartPoint + pt).x() / 2, _theStartPoint.y()));
	bezier->setC2Point(QPoint((_theStartPoint + pt).x() / 2, pt.y()));

	_theStartPoint = pt;
	_bizerList.push_back(bezier);
}

QPainterPath BezierCurves::getPath() {
	QPainterPath pathTest;
	if (_bizerList.size() <= 0) {
		return pathTest;
	}
	
	pathTest.moveTo(*(_bizerList.at(0)->getStartPoint()));
	int num = _bizerList.size();
	for (int i = 0; i < num;i++){
		BezierPoint* one = _bizerList.at(i);
		//pathTest.moveTo(*(one->getStartPoint()));
		pathTest.cubicTo((*(one->getC1Point())), *(one->getC2Point()), *(one->getEndPoint()));
	}

	return pathTest;
}

void BezierCurves::clearData() {
	_hasStartPoint = false;//是否有起点
	int num = _bizerList.size();
	for (int i = 0; i < num;i++){
		BezierPoint* one = _bizerList.at(i);
		delete one;
	}

	_bizerList.clear();
}

曲线绘制:

#pragma once
#include <QPoint>
#include <QRect>

#include <QObject>

class QPainter;
class QMouseEvent;
class BezierCurves;
class BezierPoint;

class QtBezierPath : public QObject {
	Q_OBJECT

public:
	QtBezierPath(QObject *parent);
	~QtBezierPath();

	void paint(QPainter *p);

	void mousePressEvent(QMouseEvent *event);
	void mouseMoveEvent(QMouseEvent *event);
	void mouseReleaseEvent(QMouseEvent *event);
private:
	void drawBound(QPainter *p,BezierPoint* pt);
	QRect getPointBound(QPoint* pt);
private:
	bool _leftDown = false;//鼠标左键按下
	bool _selected = false;//是否选中
	BezierCurves* _bezierCurves = nullptr;

	QPoint* _selectStartPoint = nullptr;//鼠标选中的点
	QPoint* _selectC1Point = nullptr;//鼠标选中的点
	QPoint* _selectC2Point = nullptr;//鼠标选中的点
	QPoint* _selectEndPoint = nullptr;//鼠标选中的点
};

#include "QtBezierPath.h"
#include <QMouseEvent>
#include <QPaintEvent>
#include <QTimer>
#include <QRect>
#include <QPen>
#include <QPainter>
#include "BezierCurves.h"
#include "BezierPoint.h"

QtBezierPath::QtBezierPath(QObject *parent)
	: QObject(parent) {
	_bezierCurves = new BezierCurves;
}

QtBezierPath::~QtBezierPath() {
}

void QtBezierPath::paint(QPainter *p) {

	p->setRenderHint(QPainter::Antialiasing, true);
	QPen pen;
	pen.setColor(QColor(255, 0, 0));
	if (_selected) {
		pen.setWidth(4);
	} else {
		pen.setWidth(2);
	}
	pen.setStyle(Qt::SolidLine);
	p->setPen(pen);
	p->drawPath(_bezierCurves->getPath());

	QVector<BezierPoint*>&bezierList = _bezierCurves->getBezierPoint();
	int num = bezierList.size();
	for (int i = 0; i < num;i++) {
		BezierPoint* pt = bezierList.at(i);
		p->drawLine(*(pt->getStartPoint()), *(pt->getC1Point()));
		p->drawLine(*(pt->getEndPoint()), *(pt->getC2Point()));

		pen.setWidth(2);

		drawBound(p, pt);
	}
}

void QtBezierPath::mousePressEvent(QMouseEvent *event) {
	if (event->button() == Qt::LeftButton){
		_leftDown = true;
		if (_selected){
			return;
		}
		if (!_bezierCurves->hasStartPoint()){
			_bezierCurves->setStartPoint(event->pos());
		} else {
			_bezierCurves->setNextPoint(event->pos());
		}
	}else if (event->button() == Qt::RightButton){
		_bezierCurves->clearData();
	}
}

void QtBezierPath::mouseMoveEvent(QMouseEvent *event) {
	QPoint mousePt = event->pos();
	if (_leftDown){//鼠标左键按下
		if (_selectStartPoint){
			_selectStartPoint->setX(mousePt.x());
			_selectStartPoint->setY(mousePt.y());
		}
		if (_selectC1Point) {
			_selectC1Point->setX(mousePt.x());
			_selectC1Point->setY(mousePt.y());
		}
		if (_selectC2Point) {
			_selectC2Point->setX(mousePt.x());
			_selectC2Point->setY(mousePt.y());
		}
		if (_selectEndPoint) {
			_selectEndPoint->setX(mousePt.x());
			_selectEndPoint->setY(mousePt.y());

			_bezierCurves->getTheStartPoint().setX(mousePt.x());
			_bezierCurves->getTheStartPoint().setY(mousePt.y());
		}
	} else {
		QVector<BezierPoint*>&bezierList = _bezierCurves->getBezierPoint();
		int num = bezierList.size();
		_selected = false;

		_selectStartPoint = nullptr;
		_selectC1Point = nullptr;
		_selectC2Point = nullptr;
		_selectEndPoint = nullptr;

		for (int i = 0; i < num; i++) {
			BezierPoint* bezierPt = bezierList.at(i);

			if (getPointBound(bezierPt->getStartPoint()).contains(mousePt)) {
				_selectStartPoint = bezierPt->getStartPoint();
				_selected = true;
			}
			if (getPointBound(bezierPt->getEndPoint()).contains(mousePt)) {
				_selectEndPoint = bezierPt->getEndPoint();
				_selected = true;
			}
			if (getPointBound(bezierPt->getC1Point()).contains(mousePt)) {
				_selectC1Point = bezierPt->getC1Point();
				_selected = true;
			}
			if (getPointBound(bezierPt->getC2Point()).contains(mousePt)) {
				_selectC2Point = bezierPt->getC2Point();
				_selected = true;
			}
			
		}
	
	}
}

void QtBezierPath::mouseReleaseEvent(QMouseEvent *event) {
	if (event->button() == Qt::LeftButton) {
		_leftDown = false;
	}
}

void QtBezierPath::drawBound(QPainter *p,BezierPoint* pt) {
	QRect rectBound;
	p->drawEllipse(getPointBound(pt->getStartPoint()));
	p->drawEllipse(getPointBound(pt->getC1Point()));

	p->drawEllipse(getPointBound(pt->getC2Point()));
	p->drawEllipse(getPointBound(pt->getEndPoint()));
}

QRect QtBezierPath::getPointBound(QPoint* pt) {
	QRect rectBound;
	rectBound.setLeft(pt->x() - 5);
	rectBound.setTop(pt->y() - 5);
	rectBound.setWidth(10);
	rectBound.setHeight(10);
	return rectBound;
}

aaa

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值