效果演示:
主模块代码:
MeasureGraphView::MeasureGraphView(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
m_measureType = NoType;
m_bll = BllData::getInstance();
m_scene = new GraphicsScene;
connect(m_bll, &BllData::pressMeasurePosSignal, this, &MeasureGraphView::pressMeasurePosSlot);
connect(m_bll, &BllData::returnDeletePosSignal, this, &MeasureGraphView::returnDeletePosSlot);
// 隐藏水平/竖直滚动条
ui.graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui.graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// 设置场景范围
ui.graphicsView->setSceneRect(INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX);
// 反锯齿
ui.graphicsView->setRenderHints(QPainter::Antialiasing);
m_scene->setBackgroundBrush(Qt::gray);
ui.graphicsView->setScene(m_scene);
}
MeasureGraphView::~MeasureGraphView()
{
}
void MeasureGraphView::on_disBtn_clicked() {
m_measureType = DistanceType;
m_bll->setMeasureEnable(m_measureType);
}
void MeasureGraphView::on_agBtn_clicked() {
m_measureType = AngleType;
m_bll->setMeasureEnable(m_measureType);
}
void MeasureGraphView::on_plineBtn_clicked() {
m_measureType = PToLineType;
m_bll->setMeasureEnable(m_measureType);
}
void MeasureGraphView::on_deleteBtn_clicked() {
m_bll->deleteShapeEnable();
}
void MeasureGraphView::on_clearBtn_clicked() {
m_scene->clear();
}
void MeasureGraphView::pressMeasurePosSlot(QPointF pos, PointType type) {
if (m_measureType == DistanceType) {
if (type == TopLeft) {
MeasureBase* disMeasure = new MeasureBase(DistanceType);
m_shapeList.append(disMeasure);
m_scene->addItem(disMeasure);
disMeasure->appendPoint(pos, TopLeft);
}
else if (type == BottomRight) {
m_shapeList[m_shapeList.size() - 1]->appendPoint(pos, BottomRight);
m_measureType = NoType;
}
}
else if (m_measureType == AngleType) {
if (type == FPoint) {
MeasureBase* agMeasure = new MeasureBase(AngleType);
m_shapeList.append(agMeasure);
m_scene->addItem(agMeasure);
agMeasure->appendPoint(pos, FPoint);
}
else if (type == AnglePoint) {
m_shapeList[m_shapeList.size() - 1]->appendPoint(pos, AnglePoint);
}
else {
m_shapeList[m_shapeList.size() - 1]->appendPoint(pos, EdgePoint);
m_measureType = NoType;
}
}
else if (m_measureType == PToLineType) {
if (type == FPoint) {
MeasureBase* pl = new MeasureBase(PToLineType);
m_shapeList.append(pl);
m_scene->addItem(pl);
pl->appendPoint(pos, FPoint);
}
else if (type == EdgePoint) {
m_shapeList[m_shapeList.size() - 1]->appendPoint(pos, EdgePoint);
}
else {
m_shapeList[m_shapeList.size() - 1]->appendPoint(pos, PPoint);
m_measureType = NoType;
}
}
}
void MeasureGraphView::returnDeletePosSlot(QPointF pos) {
for (int i = 0; i < m_scene->items().size(); i++) {
MeasureBase* item = (MeasureBase*)m_scene->items()[i];
QPointF lt = item->getTopLeft();
if (pos == lt) {
qDebug() << "index: " << i;
m_scene->removeItem(item);
break;
}
}
m_scene->update();
}
Scene代码:
GraphicsScene::GraphicsScene(QObject *parent)
: QGraphicsScene(parent)
{
m_enable = false;
m_bll = BllData::getInstance();
connect(m_bll, &BllData::setMeasureEnableSignal, this, &GraphicsScene::setMeasureEnableSlot);
}
GraphicsScene::~GraphicsScene()
{}
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent* event) {
if (m_enable) {
m_clickCnt++;
if (m_type == DistanceType) {
if (m_clickCnt == 1) {
m_bll->pressMeasurePos(event->scenePos(), TopLeft);
}
else if (m_clickCnt == 2) {
m_enable = false;
m_bll->pressMeasurePos(event->scenePos(), BottomRight);
}
}
else if (m_type == AngleType) {
if (m_clickCnt == 1) {
m_bll->pressMeasurePos(event->scenePos(), FPoint);
}
else if (m_clickCnt == 2) {
m_bll->pressMeasurePos(event->scenePos(), AnglePoint);
}
else if (m_clickCnt == 3) {
m_enable = false;
m_bll->pressMeasurePos(event->scenePos(), EdgePoint);
}
}
else if (m_type == PToLineType) {
if (m_clickCnt == 1) {
m_bll->pressMeasurePos(event->scenePos(), FPoint);
}
else if (m_clickCnt == 2) {
m_bll->pressMeasurePos(event->scenePos(), EdgePoint);
}
else if (m_clickCnt == 3) {
m_enable = false;
m_bll->pressMeasurePos(event->scenePos(), PPoint);
}
}
}
else {
QGraphicsScene::mousePressEvent(event);
}
}
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
QGraphicsScene::mouseMoveEvent(event);
}
void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
QGraphicsScene::mouseReleaseEvent(event);
}
void GraphicsScene::setMeasureEnableSlot(MeasureType type) {
m_type = type;
m_enable = true;
m_clickCnt = 0;
}
MeasureShape代码:
MeasureBase::MeasureBase(MeasureType type)
{
m_type = type;
m_deleteEnable = false;
m_bll = BllData::getInstance();
connect(m_bll, &BllData::deleteShapeEnableSignal, this, &MeasureBase::deleteShapeEnableSlot);
m_pen_noSelected.setColor(QColor(0, 160, 230));
m_pen_noSelected.setWidth(2);
m_pen_isSelected.setColor(QColor(255, 0, 255));
m_pen_isSelected.setWidth(2);
this->setPen(m_pen_noSelected);
this->setFlags(QGraphicsItem::ItemIsSelectable |
QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable);
}
MeasureBase::~MeasureBase()
{
}
QRectF MeasureBase::boundingRect() const {
int w = abs(m_tl.x() - m_br.x());
int h = abs(m_tl.y() - m_br.y());
int x0 = m_tl.x() < m_br.x() ? m_tl.x() : m_br.x();
int y0 = m_tl.y() < m_br.y() ? m_tl.y() : m_br.y();
QPointF center(x0 + w / 2, y0 + h / 2);
w = w > 100 ? w : 100;
h = h > 50 ? h : 50;
int xx0 = center.x() - w / 2;
int yy0 = center.y() - h / 2;
QRectF rect(xx0, yy0, w, h);
return rect;
}
void MeasureBase::focusInEvent(QFocusEvent* event) {
Q_UNUSED(event);
this->setPen(m_pen_isSelected);
}
void MeasureBase::focusOutEvent(QFocusEvent* event) {
Q_UNUSED(event);
this->setPen(m_pen_noSelected);
}
void MeasureBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setPen(this->pen());
painter->setBrush(this->brush());
int w = abs(m_tl.x() - m_br.x());
int h = abs(m_tl.y() - m_br.y());
int x0 = m_tl.x() < m_br.x() ? m_tl.x() : m_br.x();
int y0 = m_tl.y() < m_br.y() ? m_tl.y() : m_br.y();
if (m_type == DistanceType) {
double dis = sqrt(pow(m_tl.x() - m_br.x(), 2) + pow(m_tl.y() - m_br.y(), 2));
//dis = qRound(dis * 100) * 0.01;
painter->drawLine(m_tl, m_br);
if (dis > 5) {
painter->setPen(QPen(QColor(255, 64, 64)));
QPointF center(x0 + w / 2, y0 + h / 2);
QString disStr = QString::number((int)dis).append(" pix");
painter->drawText(center, disStr);
}
}
else if (m_type == AngleType) {
if (m_list.size() == 3) {
calAg();
QLineF line1(m_list[0], m_list[1]);
QLineF line2(m_list[1], m_list[2]);
painter->drawLine(line1);
painter->drawLine(line2);
painter->setPen(QPen(Qt::darkRed, 2, Qt::SolidLine));
QRectF rect(m_list[1].x() - 16, m_list[1].y() - 16, 32, 32);
painter->drawPie(rect, m_ags * 16, m_agr * 16);
QString strag = "";
m_agr = qRound(m_agr * 100) * 0.01;
strag.append(QString::number(abs(m_agr))).append("°");
painter->drawText(m_center.x()- m_radius/3, m_center.y(), strag);
}
}
else if (m_type == PToLineType) {
if (m_list.size() == 3) {
//qDebug() << "m_type == PToLineType ----------";
calData();
QLineF line1(m_list[0], m_list[1]);
QLineF line2(m_list[2], m_intersectionP);
painter->drawLine(line1);
painter->setPen(QPen(Qt::darkGreen, 2, Qt::DashLine));
painter->drawLine(line2);
painter->setPen(QPen(QBrush(QColor(255, 106, 106)), 2, Qt::SolidLine));
QString strldis = "LDis: ";
strldis.append(QString::number(m_disH)).append(" pix");
painter->drawText(m_center.x() -m_radius+10, m_center.y() -m_radius/2, strldis);
QString strlvdis = "LVDis: ";
strlvdis.append(QString::number(m_disV)).append(" pix");
painter->drawText(m_center.x() - m_radius+10, m_center.y() - m_radius / 2+20, strlvdis);
}
}
this->update();
}
void MeasureBase::calData() {
int x1 = m_list[0].x();
int y1 = m_list[0].y();
int x2 = m_list[1].x();
int y2 = m_list[1].y();
int x3 = m_list[2].x();
int y3 = m_list[2].y();
if (x2 - x1 != 0) {
double k = (double)(y2 - y1) / (x2 - x1);
if (k != 0) {
double b = (double)(y1 - k * x1);
double vk = -1 / k;
double vb = (double)(y3 - vk * x3);
double x = (vb - b) / (k - vk);
double y = k * x + b;
m_intersectionP.setX(x);
m_intersectionP.setY(y);
}
else {
qDebug() << "x1==x2";
m_intersectionP.setX(x3);
m_intersectionP.setY(y1);
}
}
else {
m_intersectionP.setX(x1);
m_intersectionP.setY(y3);
}
double DD = (y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1);
double D = sqrt(DD);
m_disH = D;
int x4 = m_intersectionP.x();
int y4 = m_intersectionP.y();
double ff = (y4 - y3) * (y4 - y3) + (x4 - x3) * (x4 - x3);
double f = sqrt(ff);
m_disV = f;
}
void MeasureBase::updatePosData(MeasureType type, QPointF org, QPointF pos) {
//QList<QPointF> list;
m_list.clear();
for (int i = 0; i < m_pointList.size(); i++) {
QPointF p = m_pointList[i]->getPoint();
//qDebug() << " list index : " << i << " pos: " << p << " org: " << org;
if ((abs(p.x() - org.x()) <= 2) && (abs(p.y() - org.y()) <= 2)) {
//qDebug() << "find it------------------------";
m_pointList[i]->setPoint(pos);
}
m_list.append(m_pointList[i]->getPoint());
}
m_center = getCentroid();
getMaxLength();
QRectF(m_center.x() - m_radius, m_center.y() - m_radius, m_radius * 2, m_radius * 2);
m_tl = QPointF(m_center.x() - m_radius, m_center.y() - m_radius);
m_br = QPointF(m_center.x() + m_radius, m_center.y() + m_radius);
this->update();
}
void MeasureBase::calAg() {
QPointF p0 = m_list[1];
QPointF p1 = m_list[0];
QPointF p2 = m_list[2];
QPoint p3(p0.x() + 100, p0.y());
QPoint p0p1;
p0p1.setX(p1.x() - p0.x());
p0p1.setY(p0.y() - p1.y());
QPoint p0p2;
p0p2.setX(p2.x() - p0.x());
p0p2.setY(p0.y() - p2.y());
QPoint p0p3;
p0p3.setX(p3.x() - p0.x());
p0p3.setY(p0.y() - p3.y());
double cosp1p2_1 = p0p1.x() * p0p2.x() + p0p1.y() * p0p2.y();
double cosp1p2_2 = sqrt(p0p1.x() * p0p1.x() + p0p1.y() * p0p1.y()) * sqrt(p0p2.x() * p0p2.x() + p0p2.y() * p0p2.y());
double cosp1p2 = cosp1p2_1 / cosp1p2_2;
double agp1p2 = abs(acos(cosp1p2)) * 180 / 3.1415926;
double cosp2p3_1 = p0p2.x() * p0p3.x() + p0p2.y() * p0p3.y();
double cosp2p3_2 = sqrt(p0p2.x() * p0p2.x() + p0p2.y() * p0p2.y()) * sqrt(p0p3.x() * p0p3.x() + p0p3.y() * p0p3.y());
double cosp2p3 = cosp2p3_1 / cosp2p3_2;
double agp2p3 = abs(acos(cosp2p3)) * 180 / 3.1415926;
double d = p0p2.x() * p0p1.y() - p0p1.x() * p0p2.y();
if (p2.y() > p0.y()) {
agp2p3 = -agp2p3;
}
if (d < 0) {
agp1p2 = -agp1p2;
}
m_ags = agp2p3;
m_agr = agp1p2;
this->update();
}
void MeasureBase::mousePressEvent(QGraphicsSceneMouseEvent* event) {
if (m_deleteEnable) {
m_deleteEnable = false;
m_bll->returnDeletePos(m_tl);
}
}
void MeasureBase::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
qreal dx = event->scenePos().x() - event->lastScenePos().x();
qreal dy = event->scenePos().y() - event->lastScenePos().y();
this->moveBy(dx, dy);
this->update();
}
void MeasureBase::setTopLeft(QPointF pos) {
m_tl = pos;
}
QPointF MeasureBase::getTopLeft() {
return m_tl;
}
void MeasureBase::setBottomRight(QPointF pos) {
m_br = pos;
}
QPointF MeasureBase::getBottomRight() {
return m_br;
}
void MeasureBase::setDot(QPointF pos) {
m_dot = pos;
}
QPointF MeasureBase::getDot() {
return m_dot;
}
void MeasureBase::appendPoint(QPointF pos, PointType type) {
if (m_type == DistanceType) {
if (type == TopLeft) {
setTopLeft(pos);
setBottomRight(pos);
PointBase* p1 = new PointBase(DistanceType, TopLeft, pos);
p1->setParentItem(this);
p1->setBrush(QBrush(QColor(0, 255, 0)));
m_pointList.append(p1);
}
else if (type == BottomRight) {
setBottomRight(pos);
PointBase* p2 = new PointBase(DistanceType, BottomRight, pos);
p2->setParentItem(this);
p2->setBrush(QBrush(QColor(0, 255, 0)));
m_pointList.append(p2);
this->update();
}
}
else if (m_type == AngleType) {
if (type == FPoint) {
m_list.append(pos);
setTopLeft(pos);
setBottomRight(pos);
PointBase* p1 = new PointBase(AngleType, FPoint, pos);
p1->setParentItem(this);
p1->setBrush(QBrush(QColor(0, 255, 0)));
m_pointList.append(p1);
}
else if (type == AnglePoint) {
m_list.append(pos);
m_center = getCentroid();
getMaxLength();
QRectF(m_center.x() - m_radius, m_center.y() - m_radius, m_radius * 2, m_radius * 2);
m_tl = QPointF(m_center.x() - m_radius, m_center.y() - m_radius);
m_br = QPointF(m_center.x() + m_radius, m_center.y() + m_radius);
PointBase* p = new PointBase(AngleType, AnglePoint,pos);
p->setParentItem(this);
p->setBrush(QBrush(QColor(255, 0, 0)));
m_pointList.append(p);
}
else {
m_list.append(pos);
m_center = getCentroid();
getMaxLength();
QRectF(m_center.x() - m_radius, m_center.y() - m_radius, m_radius * 2, m_radius * 2);
m_tl = QPointF(m_center.x() - m_radius, m_center.y() - m_radius);
m_br = QPointF(m_center.x() + m_radius, m_center.y() + m_radius);
PointBase* p = new PointBase(AngleType, EdgePoint, pos);
p->setParentItem(this);
p->setBrush(QBrush(QColor(0, 255, 0)));
m_pointList.append(p);
}
}
else if (m_type == PToLineType) {
if (type == FPoint) {
m_list.append(pos);
setTopLeft(pos);
setBottomRight(pos);
PointBase* p1 = new PointBase(PToLineType, FPoint, pos);
p1->setParentItem(this);
p1->setBrush(QBrush(QColor(0, 255, 0)));
m_pointList.append(p1);
}
else if (type == EdgePoint) {
m_list.append(pos);
m_center = getCentroid();
getMaxLength();
QRectF(m_center.x() - m_radius, m_center.y() - m_radius, m_radius * 2, m_radius * 2);
m_tl = QPointF(m_center.x() - m_radius, m_center.y() - m_radius);
m_br = QPointF(m_center.x() + m_radius, m_center.y() + m_radius);
PointBase* p = new PointBase(PToLineType, EdgePoint, pos);
p->setParentItem(this);
p->setBrush(QBrush(QColor(0, 255, 0)));
m_pointList.append(p);
}
else {
m_list.append(pos);
m_center = getCentroid();
getMaxLength();
QRectF(m_center.x() - m_radius, m_center.y() - m_radius, m_radius * 2, m_radius * 2);
m_tl = QPointF(m_center.x() - m_radius, m_center.y() - m_radius);
m_br = QPointF(m_center.x() + m_radius, m_center.y() + m_radius);
PointBase* p = new PointBase(PToLineType, PPoint, pos);
p->setParentItem(this);
p->setBrush(QBrush(QColor(255, 0, 0)));
m_pointList.append(p);
}
}
}
QPointF MeasureBase::getCentroid() {
qreal x = 0;
qreal y = 0;
if (m_list.size() > 1) {
for (int i = 0; i < m_list.size(); i++) {
x += m_list[i].x();
y += m_list[i].y();
}
x = x / m_list.size();
y = y / m_list.size();
}
return QPointF(x, y);
}
void MeasureBase::getMaxLength() {
QVector<qreal> vec;
for (auto& temp : m_list)
{
qreal dis = sqrt(pow(m_center.x() - temp.x(), 2) + pow(m_center.y() - temp.y(), 2));
vec.append(dis);
}
qreal ret = 0;
for (auto& temp : vec)
{
if (temp > ret) {
ret = temp;
}
}
m_radius = ret;
}
void MeasureBase::deleteShapeEnableSlot() {
m_deleteEnable = true;
}