上一篇文章讲到了可以利用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