TB_DrawRotateRect 表示绘制旋转矩形类,在 QLabel 上实现绘制功能。其中,拖到 p0 点能实现旋转矩形的移动;拖到 p1、p2 能实现旋转矩形大小和位置的变化;拖到 p3、p4 能实现旋转矩形长度大小的变化。
QScrollArea* qScrollArea=new QScrollArea(ui->framePicture);
QHBoxLayout* layout=new QHBoxLayout(ui->framePicture);
layout->addWidget(qScrollArea);
QLabel* qLabelView=new QLabel(qScrollArea);
qLabelView->setScaledContents(true);
qLabelView->setBackgroundRole(QPalette::Background);
qLabelView->setFrameStyle(QFrame::StyledPanel);
qLabelView->setFrameShadow(QFrame::Sunken);
qLabelView->setGeometry(0, 0, qScrollArea->width(), qScrollArea->height());
qScrollArea->setWidget(qLabelView);
GRotateRectangle rect;
Mat image;
TB_DrawRotateRect* qDrawView=new TB_DrawRotateRect(qLabelView, &rect, &image);
qDrawView->setParent(qLabelView);
qDrawView->setWindowFlags(Qt::WindowStaysOnTopHint);
qDrawView->setAttribute(Qt::WA_TranslucentBackground,true);
qDrawView->setStyleSheet("background-color:transparent");
GRotateRectangle 类对象表示旋转矩形的参数对象
#define MOUSE_LENGTH_LEN 10
#define MOUSE_RADIU_LEN 5
class GRotateRectangle
{
public:
GRotateRectangle();
~GRotateRectangle(){}
private:
Point2f p0;
Point2f p1;
Point2f p2;
Point2f p3;
Point2f p4;
private:
void UpdataPoint2fApi();
void Arrow(QPointF p1, QPointF p2, QPointF &p3, QPointF &p4);
public:
void SetPosLimit(Size imageSize);
void GetMinLength(Point2f p, float& length, int& index);
void DragPointApi(QPointF point, Size imageSize, Size labelSize);
void DrawApi(QPainter* painter, QColor color1, QColor color2, Size imageSize, Size labelSize);
public:
Point2f p1_;
Point2f p2_;
float measureLength1;
float measureLength2;
bool oriented;
bool arrowed;
};
GRotateRectangle::GRotateRectangle()
{
oriented=false;
arrowed=false;
measureLength1=100;
measureLength2=10;
p1_=Point2f(200 - measureLength1, 200);
p2_=Point2f(200 + measureLength1, 200);
p1=p1_;
p2=p2_;
}
void GRotateRectangle::UpdataPoint2fApi()
{
p0=Point2f((p1.x + p2.x)/2, (p1.y + p2.y)/2);
p3=Point2f(p0.x, p0.y - measureLength1);
p4=Point2f(p0.x, p0.y + measureLength1);
float x=p2.x-p0.x;
float y=p2.y-p0.y;
double a=atan2(y, x)*180.0/CV_PI;
a = a<0 ? (360 + a) : a;
p3=cvPointRotate(p3, p0, a);
p4=cvPointRotate(p4, p0, a);
}
void GRotateRectangle::GetMinLength(Point2f p, float& length, int& index)
{
vector<Point2f> sorts;
sorts.push_back(p0);
sorts.push_back(p1);
sorts.push_back(p2);
sorts.push_back(p3);
sorts.push_back(p4);
length=10e9;
index=-1;
for(size_t i=0;i<sorts.size();i++)
{
float l=cvPointDistance(p, sorts[i]);
if(l<=length)
{
length=l;
index=(int)i;
}
}
}
void GRotateRectangle::Arrow(QPointF p1, QPointF p2, QPointF &p3, QPointF &p4)
{
QLineF line(p1, p2);
double angle=acos(line.dx()/line.length());
angle = line.dy()>=0 ? (2.0*QM_PI - angle) : angle;
float len=QPointDistance(p1, p2) / MOUSE_RADIU_LEN;
len = len<=1 ? 1 : len;
p3=p2 + QPointF(sin(angle - QM_PI/3)*len, cos(angle - QM_PI/3)*len);
p4=p2 + QPointF(sin(angle - QM_PI + QM_PI/3)*len, cos(angle - QM_PI + QM_PI/3)*len);
}
void GRotateRectangle::SetPosLimit(Size imageSize)
{
int w=imageSize.width;
int h=imageSize.height;
if(w==0 || h==0)
return;
p1.x = p1.x<0 ? 0 : (p1.x>=w ? w-1 : p1.x);
p2.x = p2.x<0 ? 0 : (p2.x>=w ? w-1 : p2.x);
p1.y = p1.y<0 ? 0 : (p1.y>=h ? h-1 : p1.y);
p2.y = p2.y<0 ? 0 : (p2.y>=h ? h-1 : p2.y);
if(p1.x==p2.x && p1.y==p2.y && (p1.x==0 || p1.x==w-1) && (p1.y==0 || p1.y==h-1))
{
p1=Point2f(w/2 - 10, h/2);
p2=Point2f(w/2 + 10, h/2);
}
float l=(float)sqrt((double)(w*w + h*h))/2;
measureLength1 = measureLength1>l ? l : measureLength1;
}
void GRotateRectangle::DragPointApi(QPointF point, Size imageSize, Size labelSize)
{
float sX=(float)imageSize.width/labelSize.width;
float sY=(float)imageSize.height/labelSize.height;
float sZ=(sX + sY)/2;
Point2f p(point.x()*sX, point.y()*sY);
int index;
float length;
this->GetMinLength(p, length, index);
if(length<=(MOUSE_LENGTH_LEN*sZ))
{
switch(index)
{
case 0:
{
float x=p.x-p0.x;
float y=p.y-p0.y;
p1=Point2f(p1.x+x, p1.y+y);
p2=Point2f(p2.x+x, p2.y+y);
break;
}
case 1:
p1=Point2f(p.x, p.y);
break;
case 2:
p2=Point2f(p.x, p.y);
break;
case 3:
case 4:
measureLength1=cvPointDistance(p, p0);
break;
default:
break;
}
}
this->SetPosLimit(imageSize);
}
void GRotateRectangle::DrawApi(QPainter* painter, QColor color1, QColor color2, Size imageSize, Size labelSize)
{
float sX=(float)imageSize.width/labelSize.width;
float sY=(float)imageSize.height/labelSize.height;
if(!(labelSize.width>0 && imageSize.width>0))
return;
this->UpdataPoint2fApi();
QPointF P0(p0.x/sX, p0.y/sY);
QPointF P1(p1.x/sX, p1.y/sY);
QPointF P2(p2.x/sX, p2.y/sY);
QPointF P3(p3.x/sX, p3.y/sY);
QPointF P4(p4.x/sX, p4.y/sY);
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setPen(color1);
QRectF rect3(P0.x()-MOUSE_RADIU_LEN, P0.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
painter->drawEllipse(rect3);
QRectF rect4(P1.x()-MOUSE_RADIU_LEN, P1.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
painter->drawEllipse(rect4);
QRectF rect5(P2.x()-MOUSE_RADIU_LEN, P2.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
painter->drawEllipse(rect5);
painter->setPen(color2);
QRectF rect1(P3.x()-MOUSE_RADIU_LEN, P3.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
painter->drawEllipse(rect1);
QRectF rect2(P4.x()-MOUSE_RADIU_LEN, P4.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
painter->drawEllipse(rect2);
QPointF l1=QPointF(P1.x() + P3.x() - P0.x(), P1.y() + P3.y() - P0.y());
QPointF l2=QPointF(P1.x() + P4.x() - P0.x(), P1.y() + P4.y() - P0.y());
QPointF l3=QPointF(P2.x() + P4.x() - P0.x(), P2.y() + P4.y() - P0.y());
QPointF l4=QPointF(P2.x() + P3.x() - P0.x(), P2.y() + P3.y() - P0.y());
painter->drawLine(l1, l2);
painter->drawLine(l2, l3);
painter->drawLine(l3, l4);
painter->drawLine(l4, l1);
if(!arrowed)
return;
QPointF l5=QPointF((l1.x() + P3.x())/2, (l1.y() + P3.y())/2);
QPointF l6=QPointF((l2.x() + P4.x())/2, (l2.y() + P4.y())/2);
QPointF l7=QPointF(P3.x(), P3.y());
QPointF l8=QPointF(P4.x(), P4.y());
QPointF l9=QPointF((l4.x() + P3.x())/2, (l4.y() + P3.y())/2);
QPointF l10=QPointF((l3.x() + P4.x())/2, (l3.y() + P4.y())/2);
painter->drawLine(l5, l6);
painter->drawLine(l7, l8);
painter->drawLine(l9, l10);
QPointF s1 = oriented ? l5 : l6;
QPointF e1 = oriented ? l6 : l5;
QPointF s2 = oriented ? l7 : l8;
QPointF e2 = oriented ? l8 : l7;
QPointF s3 = oriented ? l9 : l10;
QPointF e3 = oriented ? l10 : l9;
QPointF a1, a2, a3, a4, a5, a6;
this->Arrow(s1, e1, a1, a2);
this->Arrow(s2, e2, a3, a4);
this->Arrow(s3, e3, a5, a6);
painter->drawLine(a1, e1);
painter->drawLine(a2, e1);
painter->drawLine(a3, e2);
painter->drawLine(a4, e2);
painter->drawLine(a5, e3);
painter->drawLine(a6, e3);
}
TB_DrawRotateRect 类实现拖到、绘制等功能
class TB_DrawRotateRect : public QWidget
{
Q_OBJECT
public:
explicit TB_DrawRotateRect(QWidget* parent, GRotateRectangle* rect, Mat* image);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void paintEvent(QPaintEvent *event);
~TB_DrawRotateRect(){}
public:
GRotateRectangle* pGraphic;
Mat* pImageSize;
};
TB_DrawRotateRect::TB_DrawRotateRect(QWidget* parent, GRotateRectangle* rect, Mat* image) :
QWidget(parent), pImageSize(image),
pGraphic(rect)
{}
void TB_DrawRotateRect::mouseMoveEvent(QMouseEvent *e)
{
if(!(e->buttons() & Qt::LeftButton))
return;
int x=e->x();
int y=e->y();
if(x<0 || y<0 || x>this->width() || y>this->height() || !pImageSize)
return;
QPointF point(x, y);
Size imageSize(pImageSize->cols, pImageSize->rows);
Size labelSize(this->width(), this->height());
pGraphic->DragPointApi(point, imageSize, labelSize);
}
void TB_DrawRotateRect::mouseReleaseEvent(QMouseEvent *e)
{
e->accept();
}
void TB_DrawRotateRect::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
if(!pImageSize)
return;
Size imageSize(pImageSize->cols, pImageSize->rows);
Size labelSize(this->width(), this->height());
pGraphic->DrawApi(&painter, Qt::blue, Qt::red, imageSize, labelSize);
this->update();
}