GraphView实现绘图工具进阶版

效果演示:

主模块代码:

csharp 复制代码
GraphViewProject::GraphViewProject(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    m_shapeType = NoType;
    m_bll = BllData::getInstance();
    m_scene = new GraphicsScene;
    connect(m_bll, &BllData::pressShapePosSignal, this, &GraphViewProject::pressShapePosSlot);
    connect(m_bll, &BllData::returnPolygonPosSignal, this, &GraphViewProject::returnPolygonPosSlot);
    connect(m_bll, &BllData::returnDeletePosSignal, this, &GraphViewProject::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);
}
GraphViewProject::~GraphViewProject()
{

}
void GraphViewProject::pressShapePosSlot(QPointF pos, PointType type) {
    if (m_shapeType == RectType) {
        if (type == TopLeft) {
            ShapeBase* rec = new ShapeBase(RectType);
            m_shapeList.append(rec);
            m_scene->addItem(rec);
            rec->appendPoint(pos, TopLeft);
        }
        else if (type == BottomRight) {
            m_shapeList[m_shapeList.size() - 1]->appendPoint(pos, BottomRight);
            m_shapeType = NoType;
        }
    }
    else if (m_shapeType==CircleType) {
        if (type == Center) {
            ShapeBase* cir = new ShapeBase(CircleType);
            m_shapeList.append(cir);
            m_scene->addItem(cir);
            cir->appendPoint(pos, Center);
        }
        else if (type == Dot) {
            m_shapeList[m_shapeList.size() - 1]->appendPoint(pos, Dot);
            m_shapeType = NoType;
        }
    }
    else if (m_shapeType == EllipseType) {
        ShapeBase* ellipse = new ShapeBase(EllipseType);
        m_shapeList.append(ellipse);
        m_scene->addItem(ellipse);
        ellipse->appendPoint(pos, Center);
        m_shapeType = NoType;
    }
  }
void GraphViewProject::returnPolygonPosSlot(QPointF pos, QList<QPointF> list, bool flag) {
    if (list.size() == 1) {
        ShapeBase* polygon = new ShapeBase(PolygonType);
        m_shapeList.append(polygon);
        m_scene->addItem(polygon);
        polygon->appendPolygonPoint(pos, list,flag);
    }
    else {
        m_shapeList[m_shapeList.size() - 1]->appendPolygonPoint(pos, list, flag);
        if (flag) {
            m_shapeType = NoType;
        }
    }
}
void GraphViewProject::returnDeletePosSlot(QPointF pos) {
    for (int i = 0; i < m_scene->items().size(); i++) {
        ShapeBase* item = (ShapeBase*)m_scene->items()[i];
        QPointF lt = item->getTopLeft();
        if (pos == lt) {
            qDebug() << "index: " << i;
            m_scene->removeItem(item);
            break;
        }
    }
}
void GraphViewProject::on_rectBtn_clicked() {
    m_shapeType = RectType;
    m_bll->setShapeEnable(RectType);
}
void GraphViewProject::on_circleBtn_clicked() {
    m_shapeType = CircleType;
    m_bll->setShapeEnable(CircleType);
}
void GraphViewProject::on_ellipseBtn_clicked() {
    m_shapeType = EllipseType;
    m_bll->setShapeEnable(EllipseType);
}
void GraphViewProject::on_polygonBtn_clicked() {
    m_shapeType = PolygonType;
    m_bll->setShapeEnable(PolygonType);
}
void GraphViewProject::on_deleteBtn_clicked() {
    m_bll->deleteShapeEnable();
}
void GraphViewProject::on_clearBtn_clicked() {
    m_scene->clear();
}

Scene代码:

csharp 复制代码
GraphicsScene::GraphicsScene(QObject *parent)
	: QGraphicsScene(parent)
{
	m_enable = false;
	m_bll = BllData::getInstance();
	connect(m_bll, &BllData::setShapeEnableSignal, this, &GraphicsScene::setShapeEnableSlot);
}
GraphicsScene::~GraphicsScene()
{}
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent* event) {
	if (m_enable) {
		m_clickCnt++;
		if (m_type == RectType) {
			if (m_clickCnt == 1) {
				m_bll->pressShapePos(event->scenePos(), TopLeft);
			}
			else if (m_clickCnt == 2) {
				m_enable = false;
				m_bll->pressShapePos(event->scenePos(), BottomRight);
			}
		}
		else if (m_type == CircleType) {
			if (m_clickCnt == 1) {
				m_bll->pressShapePos(event->scenePos(), Center);
			}
			else if (m_clickCnt == 2) {
				m_enable = false;
				m_bll->pressShapePos(event->scenePos(), Dot);
			}
		}
		else if (m_type == EllipseType) {
			if (m_clickCnt == 1) {
				m_enable = false;
				m_bll->pressShapePos(event->scenePos(), Center);
			}
		}
		else if (m_type == PolygonType) {
			if (event->buttons() == Qt::LeftButton) {
				m_list.push_back(event->scenePos());
				m_bll->returnPolygonPos(event->scenePos(), m_list, false);
			}
			else {
				if (m_list.size() >= 3) {
					m_enable = false;
					m_bll->returnPolygonPos(event->scenePos(), m_list, true);
					m_list.clear();
				}
			}
		}
	}
	else {
		QGraphicsScene::mousePressEvent(event);
	}
}
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
	QGraphicsScene::mouseMoveEvent(event);
}
void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
	QGraphicsScene::mouseReleaseEvent(event);
}
void GraphicsScene::setShapeEnableSlot(ShapeType type) {
	m_type = type;
	m_enable = true;
	m_clickCnt = 0;
	m_list.clear();
}

Shape代码:

csharp 复制代码
ShapeBase::ShapeBase(ShapeType type)
{
	m_type = type;
	m_deleteEnable = false;
	m_polygonFinshed = false;
	m_bll = BllData::getInstance();
	connect(m_bll, &BllData::deleteShapeEnableSignal, this, &ShapeBase::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);
}
ShapeBase::~ShapeBase()
{}
ShapeType ShapeBase::getType() {
	return m_type;
}
void ShapeBase::setTopLeft(QPointF tl) {
	m_tl = tl;
}
QPointF ShapeBase::getTopLeft() {
	return m_tl;
}
void ShapeBase::setBottomRight(QPointF br) {
	m_br = br;
}
QPointF ShapeBase::getBottomRight() {
	return m_br;
}
void ShapeBase::setCenter(QPointF center) {
	m_center = center;
}
QPointF ShapeBase::getCenter() {
	return m_center;
}
void ShapeBase::deleteShapeEnableSlot() {
	m_deleteEnable = true;
}
void ShapeBase::setRandColor() {
	QColor color(qrand() % 256, qrand() % 256, qrand() % 256);
	for (int i = 0; i < m_pointList.size(); i++) {
		m_pointList[i]->setBrush(QBrush(color));
	}
}
void ShapeBase::appendPoint(QPointF pos, PointType type) {
	if (m_type == RectType) {
		if (type == TopLeft) {
			setTopLeft(pos);
			setBottomRight(pos);
			PointBase* p1 = new PointBase(RectType, 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(RectType, BottomRight, pos);
			p2->setParentItem(this);
			p2->setBrush(QBrush(QColor(0, 255, 0)));
			m_pointList.append(p2);
			this->update();
		}
	}
	else if (m_type == CircleType) {
		if (type == Center) {
			setTopLeft(pos);
			setBottomRight(pos);
			setCenter(pos);
			PointBase* p1 = new PointBase(CircleType, Center, pos);
			p1->setParentItem(this);
			p1->setBrush(QBrush(QColor(0, 255, 0)));
			m_pointList.append(p1);
		}
		else if (type == Dot) {
			m_radius = sqrt(pow(m_tl.x() - pos.x(), 2) + pow(m_tl.y() - pos.y(), 2));
			double tlx = m_tl.x() - m_radius;
			double tly = m_tl.y() - m_radius;
			double brx = m_tl.x() + m_radius;
			double bry = m_tl.y() + m_radius;
			setDot(pos);
			setTopLeft(QPointF(tlx, tly));
			setBottomRight(QPointF(brx, bry));
			PointBase* p2 = new PointBase(CircleType, Dot, pos);
			p2->setParentItem(this);
			p2->setBrush(QBrush(QColor(0, 255, 0)));
			m_pointList.append(p2);
			this->update();
		}
	}
	else if (m_type == EllipseType) {
		setCenter(pos);
		PointBase* p1 = new PointBase(EllipseType, Center, pos);
		p1->setParentItem(this);
		p1->setBrush(QBrush(QColor(0, 255, 0)));
		m_pointList.append(p1);
		double tlx = pos.x() - 50;
		double tly = pos.y() - 40;
		double brx = pos.x() + 50;
		double bry = pos.y() + 40;
		setTopLeft(QPointF(tlx, tly));
		setBottomRight(QPointF(brx, bry));
		PointBase* p2 = new PointBase(EllipseType, BottomRight, QPointF(brx,bry));
		p2->setParentItem(this);
		p2->setBrush(QBrush(QColor(0, 255, 0)));
		m_pointList.append(p2);
		this->update();
	}
}
void ShapeBase::appendPolygonPoint(QPointF pos, QList<QPointF> list, bool flag) {
	m_polygonFinshed = flag;
	if (list.size() == 1) {
		setTopLeft(pos);
		setBottomRight(pos);
		PointBase* p1 = new PointBase(PolygonType, FirstDot, pos);
		p1->setParentItem(this);
		p1->setBrush(QBrush(QColor(0, 255, 0)));
		m_pointList.append(p1);
	}
	else {
		QPointF center = getCenter(list);
		QRectF rect = getBoundingRect(list);
		m_tl = rect.topLeft();
		m_br = rect.bottomRight();
		if (flag) {
			PointBase* p = new PointBase(PolygonType, Center, center);
			p->setParentItem(this);
			p->setBrush(QBrush(QColor(0, 255, 0)));
			m_pointList.append(p);
		}
		else {
			PointBase* p = new PointBase(PolygonType, OtherDot, pos);
			p->setParentItem(this);
			p->setBrush(QBrush(QColor(0, 255, 0)));
			m_pointList.append(p);
		}
	}
	this->update();
}
QPointF ShapeBase::getCentroid(QList<QPointF> list) {
	qreal x = 0;
	qreal y = 0;
	for (auto& temp : list)
	{
		x += temp.x();
		y += temp.y();
	}
	x = x / list.size();
	y = y / list.size();
	return QPointF(x, y);
}
void ShapeBase::getMaxLength() {
	QVector<qreal> vec;
	for (auto& temp : m_pointList)
	{
		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 ShapeBase::updatePolygonData(QPointF org, QPointF pos) {
	QList<QPointF> list;
	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);
		}
		list.append(m_pointList[i]->getPoint());
	}
	/*QPointF center = getCenter(list);
	qDebug() << "center:  " << center;
	QRectF rect = getBoundingRect(list);
	m_tl = rect.topLeft();
	m_br = rect.bottomRight();
	m_pointList.at(m_pointList.size() - 1)->setPoint(center);*/
	m_center = getCentroid(list);
	m_pointList.at(m_pointList.size() - 1)->setPoint(m_center);
	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);
}

QPointF ShapeBase::getCenter(QList<QPointF> list) {
	std::vector<cv::Point> contours;
	for (int i = 0; i < list.size(); i++) {
		int x = list[i].x();
		int y = list[i].y();
		contours.push_back(cv::Point(x, y));
	}
	cv::Moments moment = cv::moments(contours);
	cv::Point midPoint = cv::Point(int(moment.m10 / moment.m00), int(moment.m01 / moment.m00));
	return QPointF(midPoint.x, midPoint.y);
}
QRectF ShapeBase::getBoundingRect(QList<QPointF> list) {
	std::vector<cv::Point> contours;
	for (int i = 0; i < list.size(); i++) {
		int x = list[i].x();
		int y = list[i].y();
		contours.push_back(cv::Point(x, y));
	}
	cv::Rect rect = cv::boundingRect(contours);
	int tlx = rect.tl().x;
	int tly = rect.tl().y;
	int w = rect.width;
	int h = rect.height;
	return QRectF(tlx, tly, w, h);
}
void ShapeBase::setDot(QPointF pos) {
	m_dot = pos;
}
QPointF ShapeBase::getDot() {
	return m_dot;
}
void ShapeBase::updateRadius() {
	double radius = sqrt(pow(m_center.x() - m_dot.x(), 2) + pow(m_center.y() - m_dot.y(), 2));
	double tlx = m_center.x() - radius;
	double tly = m_center.y() - radius;
	double brx = m_center.x() + radius;
	double bry = m_center.y() + radius;
	setTopLeft(QPointF(tlx, tly));
	setBottomRight(QPointF(brx, bry));
}
void ShapeBase::updateEllipse() {
	int w = abs(m_br.x() - m_center.x());
	int h = abs(m_br.y() - m_center.y());
	double tlx = m_center.x() - w;
	double tly = m_center.y() - h;
	double brx = m_center.x() + w;
	double bry = m_center.y() + h;
	setTopLeft(QPointF(tlx, tly));
	setBottomRight(QPointF(brx, bry));
}
QRectF ShapeBase::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();
	QRectF rect(x0, y0, w, h);
	return rect;
}
void ShapeBase::focusInEvent(QFocusEvent* event) {
	Q_UNUSED(event);
	this->setPen(m_pen_isSelected);
}
void ShapeBase::focusOutEvent(QFocusEvent* event) {
	Q_UNUSED(event);
	this->setPen(m_pen_noSelected);
}
void ShapeBase::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();

	QRectF rect(x0, y0, w, h);
	if (m_type == RectType) {
		painter->drawRect(rect);
	}
	else if (m_type == CircleType) {
		painter->drawEllipse(rect);
	}
	else if (m_type == EllipseType) {
		painter->drawEllipse(rect);
	}
	else if (m_type == PolygonType) {
		if (m_polygonFinshed) {
			for (int i = 1; i < m_pointList.size() - 1; i++)
			{
				painter->drawLine(m_pointList.at(i - 1)->getPoint(), m_pointList.at(i)->getPoint());
			}
			painter->drawLine(m_pointList.at(m_pointList.size() - 2)->getPoint(), m_pointList.at(0)->getPoint());
		}
		else {
			for (int i = 1; i < m_pointList.size(); i++)
			{
				painter->drawLine(m_pointList.at(i - 1)->getPoint(), m_pointList.at(i)->getPoint());
			}
		}
	}
}
void ShapeBase::mousePressEvent(QGraphicsSceneMouseEvent* event) {
	if (m_deleteEnable) {
		m_bll->returnDeletePos(m_tl);
	}
}
void ShapeBase::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
	qreal dx = event->scenePos().x() - event->lastScenePos().x();
	qreal dy = event->scenePos().y() - event->lastScenePos().y();
	this->moveBy(dx, dy);
}
相关推荐
矛取矛求2 小时前
QT的前景与互联网岗位发展
开发语言·qt
Leventure_轩先生2 小时前
[WASAPI]从Qt MultipleMedia来看WASAPI
开发语言·qt
晓纪同学11 小时前
QT-简单视觉框架代码
开发语言·qt
威桑11 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服11 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
fyzy11 小时前
Qt获取本地计算的CPU温度
qt
cbdg375711 小时前
Qt 6 QML Settings location 不创建指定路径文件
qt
了一li11 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
杨德杰11 小时前
QT网络(一):主机信息查询
网络·qt
黄金右肾12 小时前
Qt之串口设计-线程实现(十二)
qt·thread·serialport