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);
}
相关推荐
四维碎片1 天前
【Qt】UDP跨平台调试工具
qt·学习·udp
踏过山河,踏过海1 天前
【用ui文件做个简单工具的开发,为什么修改完ui后,程序重新编译运行后,GUI界面还是不变呢?】
qt·ui
向阳开的夏天1 天前
麒麟V10源码编译QT5.6.3 (x86 & arm64)
开发语言·qt
打码的猿1 天前
Qt对话框不锁死主程序的方法
开发语言·qt
小小码农Come on1 天前
Qt Creator常用设置
qt
wkm9561 天前
在arm64 ubuntu系统安装Qt后编译时找不到Qt3DExtras头文件
开发语言·arm开发·qt
小小码农Come on2 天前
QT开发环境安装
开发语言·qt
小小码农Come on2 天前
QT内存管理
开发语言·qt
有理想的打工人2 天前
QT的安装
qt
SilentSlot2 天前
【QT-QML】8. 输入元素
qt·qml