[Qt+VS2013]如何实现通过拖动图形的边改变其大小

晴空飞一鹤 软件工程师  2016-08-23 01:30:55
在Qt+VS2013的程序中,我使用QPolygonF类定义了一个对象myPolygon,并用这个对象绘制了菱形、矩形、平行四边形等,当我把这几个图形拖动到场景中的时候,想要实现“选中这个图形,出现八个可以调整这个图形的角,像Visio图中那样,可以用鼠标拖动,改变图形大小”,我试了好几个函数,都不太成功。有大神知道没?
QPainterPath path;
switch (myDiagramType) {
case StartEnd:
path.moveTo(200, 50);
path.arcTo(150, 0, 50, 50, 0, 90);
path.arcTo(50, 0, 50, 50, 90, 90);
path.arcTo(50, 50, 50, 50, 180, 90);
path.arcTo(150, 50, 50, 50, 270, 90);
path.lineTo(200, 25);
myPolygon = path.toFillPolygon();
break;
case Conditional:
myPolygon << QPointF(-100, 0) << QPointF(0, 100)
<< QPointF(100, 0) << QPointF(0, -100)
<< QPointF(-100, 0);
break;
case Step:
myPolygon << QPointF(-100, -100) << QPointF(100, -100)
<< QPointF(100, 100) << QPointF(-100, 100)
<< QPointF(-100, -100);
break;
default:
myPolygon << QPointF(-120, -80) << QPointF(-70, 80)
<< QPointF(120, 80) << QPointF(70, -80)
<< QPointF(-120, -80);
break;
}
setPolygon(myPolygon);
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemIsSelectable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
...全文
514 6 点赞 打赏 收藏 举报
写回复
6 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
wqhua 2016-11-24
请问楼主,最后实现了吗?后面贴的源码哪里能下载到?
  • 打赏
  • 举报
回复
晴空飞一鹤 2016-08-31
if (shapType_ == SHAP_RECT || shapType_ == SHAP_ELLIPSE) //
	{
		for (int i = 0; i < 8; ++i)
		{
			QGraphicsRectItem *pPane = new QGraphicsRectItem(this);
			pPane->setCursor(Qt::SizeFDiagCursor); //当鼠标在pPane对象时,鼠标的形状
			pPane->setPen(QPen(QColor(0, 128, 0)));//设置画矩形的画笔,用的是绿色
			pPane->setBrush(QBrush(QColor(173, 235, 173)));
			pPane->setRect(0, 0, 8, 8); //坐标(0,0),宽和高均为8的矩形
			pPane->setData(0, 10 + i);
			panes_.insert(i, pPane);
			if (i == 0 || i == 7)
				pPane->setCursor(Qt::SizeFDiagCursor);
			else if (i == 1 || i == 6)
				pPane->setCursor(Qt::SizeHorCursor);
			else if (i == 2 || i == 5)
				pPane->setCursor(Qt::SizeBDiagCursor);
			else if (i == 3 || i == 4)
				pPane->setCursor(Qt::SizeVerCursor);
		}
		adjustPanesPos(boundingRect());
	}
再看adjustPanesPos(QRectF &re)的实现

void FocusAgentItem::adjustPanesPos(QRectF &re)
{
	const QRectF parentRect = re;
	qreal x = 0, y = 0;
	x = parentRect.width() / 2 - 4 + re.left();
	y = 0 + re.top();
	panes_[TOP]->setPos(x, y);


	x = parentRect.width() / 2 - 4 + re.left();
	y = parentRect.height() - 8 + re.top();
	panes_[BOTTOM]->setPos(x, y);

	x = parentRect.width() - 8 + re.left();
	y = parentRect.height() / 2 - 4 + re.top();
	panes_[RIGHT]->setPos(x, y);

	x = 0 + re.left();
	y = parentRect.height() / 2 - 4 + re.top();
	panes_[LEFT]->setPos(x, y);

	x = 0 + re.left();
	y = 0 + re.top();
	panes_[LEFT_TOP]->setPos(x, y);

	x = parentRect.width() - 8 + re.left();
	y = parentRect.height() - 8 + re.top();
	panes_[RIGHT_BOTTOM]->setPos(x, y);

	x = parentRect.width() - 8 + re.left();
	y = 0 + re.top();
	panes_[RIGHT_TOP]->setPos(x, y);

	x = 0 + re.left();
	y = parentRect.height() - 8 + re.top();
	panes_[LEFT_BOTTOM]->setPos(x, y);

}

QRectF FocusAgentItem::boundingRect() const 
{
	return framRect_;
}

void FocusAgentItem::updateFrameRect(QRectF re, qreal penWidth)
{
	framRect_ = pCurrentItem_->item()->boundingRect();
	setPos(pCurrentItem_->item()->scenePos());
	if (pCurrentItem_->item()->type() == UserType + 2)
		framRect_.adjust(1 + penWidth, 1 + penWidth, -1 - penWidth, -1 - penWidth);
	else
		framRect_.adjust(-4, -4, 4, 4);
	adjustPanesPos(boundingRect());

}

void FocusAgentItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
	//curPane_ = qgraphicsitem_cast<QGraphicsItem*>(scene()->itemAt(event->scenePos()));
	QTransform deviceTransform;
	curPane_ =scene()->itemAt(event->scenePos(), deviceTransform);
	int cellId = curPane_->data(0).toInt();
	if (curPane_ && cellId >= 10)
	{
		move_ = true;
		lastPoint_.setX(event->scenePos().x());
		lastPoint_.setY(event->scenePos().y());
		QRectF boundRect = boundingRect();
		switch (shapType_)
		{
		case SHAP_RECT:
		{
			pdashRectShap_->setRect(boundRect.left() + 4, boundRect.top() + 4,
				boundRect.width() - 8, boundRect.height() - 8);
			pdashRectShap_->show();
		}
		break;
		}


	}
	else
		return QGraphicsItem::mousePressEvent(event);
}

void FocusAgentItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
	if (!move_)
		return QGraphicsItem::mouseMoveEvent(event);
	QPointF curPoint(event->scenePos());
	QPointF interval = curPoint - lastPoint_;

	int nValue = curPane_->data(0).toInt();
	QRectF boundRect = boundingRect();
	qreal qleft = boundRect.left();
	qreal qtop = boundRect.top();
	QRectF re(0, 0, 1, 1);
	switch (nValue - 10)
	{
	case RIGHT_BOTTOM:
		re.setRect(4 + qleft, 4 + qtop, boundRect.width() - 8 + interval.x(), boundRect.height() - 8 + interval.y());
		break;
	case RIGHT:
		re.setRect(4 + qleft, 4 + qtop, boundRect.width() - 8 + interval.x(), boundRect.height() - 8);
		break;
	case BOTTOM:
		re.setRect(4 + qleft, 4 + qtop, boundRect.width() - 8, boundRect.height() - 8 + interval.y());
		break;
	case LEFT_TOP:
		re.setRect(4 + interval.x() + qleft, 4 + interval.y() + qtop, boundRect.width() - 8 - interval.x(), boundRect.height() - 8 - interval.y());
		if (re.top() > framRect_.bottom() - 1 - 4)
			re.setTop(framRect_.bottom() - 1 - 4);
		if (re.bottom() > framRect_.bottom() - 4)
			re.setBottom(framRect_.bottom() - 4);

		if (re.left() > framRect_.right() - 1 - 4)
			re.setLeft(framRect_.right() - 1 - 4);
		if (re.right() > framRect_.right() - 4)
			re.setRight(framRect_.right() - 4);
		break;
	case LEFT:
		re.setRect(4 + interval.x() + qleft, 4 + qtop, boundRect.width() - 8 - interval.x(), boundRect.height() - 8);
		if (re.left() > framRect_.right() - 1 - 4)
			re.setLeft(framRect_.right() - 1 - 4);
		if (re.right() > framRect_.right() - 4)
			re.setRight(framRect_.right() - 4);
		break;
	case TOP:
		re.setRect(4 + qleft, 4 + interval.y() + qtop, boundRect.width() - 8, boundRect.height() - 8 - interval.y());
		if (re.top() > framRect_.bottom() - 1 - 4)
			re.setTop(framRect_.bottom() - 1 - 4);
		if (re.bottom() > framRect_.bottom() - 4)
			re.setBottom(framRect_.bottom() - 4);
		break;
	case LEFT_BOTTOM:
		re.setRect(4 + interval.x() + qleft, 4 + qtop, boundRect.width() - 8 - interval.x(), boundRect.height() - 8 + interval.y());
		if (re.left() > framRect_.right() - 1 - 4)
			re.setLeft(framRect_.right() - 1 - 4);
		if (re.right() > framRect_.right() - 4)
			re.setRight(framRect_.right() - 4);
		break;
	case RIGHT_TOP:
		re.setRect(4 + qleft, 4 + interval.y() + qtop, boundRect.width() - 8 + interval.x(), boundRect.height() - 8 - interval.y());
		if (re.top() > framRect_.bottom() - 1 - 4)
			re.setTop(framRect_.bottom() - 1 - 4);
		if (re.bottom() > framRect_.bottom() - 4)
			re.setBottom(framRect_.bottom() - 4);
		break;
	}

	if (re.width() < 1)
		re.setWidth(1);
	if (re.height() < 1)
		re.setHeight(1);

	switch (shapType_)
	{
	case SHAP_RECT:
		pdashRectShap_->setRect(re);
		break;
	}

}

void FocusAgentItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
	if (!move_)
		return QGraphicsItem::mouseReleaseEvent(event);

	move_ = false;
	switch (shapType_)
	{
		case SHAP_RECT:
		{
			pdashRectShap_->hide();
			framRect_.setWidth(pdashRectShap_->rect().width() + 8);
			framRect_.setHeight(pdashRectShap_->rect().height() + 8);
			framRect_ = pdashRectShap_->rect().adjusted(-4, -4, 4, 4);
			adjustPanesPos(framRect_);
			pCurrentItem_->setItemRectF(QRectF(0, 0, pdashRectShap_->rect().width(), pdashRectShap_->rect().height()));
			pCurrentItem_->setItemPos(mapToScene(pdashRectShap_->rect().topLeft()));

		}
		break;
	}
}

void FocusAgentItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /* = 0 */)
{
}
上面这些代码怎么实现我也不太懂,但看作者的源程序确实实现了矩形框的拉伸。
  • 打赏
  • 举报
回复
晴空飞一鹤 2016-08-23
引用 3 楼 u013466477 的回复:
[quote=引用 2 楼 WindFlowInTheSky 的回复:] [quote=引用 1 楼 u013466477 的回复:] 在多边形的boundingrect,每个方位画一个小正方形,用来拉伸缩放形状大小 当鼠标在某个小正方形点击并拖动,在mouseMove事件中根据offset(offset = nowPt - lastPt)改变多边形大小即可
引用 1 楼 u013466477 的回复:
在多边形的boundingrect,每个方位画一个小正方形,用来拉伸缩放形状大小 当鼠标在某个小正方形点击并拖动,在mouseMove事件中根据offset(offset = nowPt - lastPt)改变多边形大小即可
我在Qt Assist中查看了以下,说 QRectF QPolygonF::boundingRect() const 这个函数返回的是多边形的边界矩形,这个函数的返回值也是QRecfF,我怎么用它和offset结合呢?以下是我的mouseMoveEvent函数: void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) { if (myMode == InsertLine && line != 0) { QLineF newLine(line->line().p1(), mouseEvent->scenePos()); line->setLine(newLine); } else if (myMode == MoveItem) { QGraphicsScene::mouseMoveEvent(mouseEvent); } } 最后,你的头像好酷![/quote] QPainterPath 里面的数据就应该是一个宽度和高度决定的(多边形就根据宽高比例来计算,是一样的),例如: path.moveTo(0, 0); path.lineTo(width*0.5, -height*0.5); path.lineTo(width, 0); path.lineTo(width, height); path.lineTo(width*0.5, height + height*0.5); path.lineTo(0, height); path.lineTo(0, 0); 多边形,路径不变,当你改变宽度或高度路径就会被刷新,形状自然会拉伸 拉伸多少那就根据offset来算,整个过程全要用浮点来算才准 函数的返回值也是QRecfF,我怎么用它和offset结合呢? 假如你拉的是右边,那你的左顶点肯定不变,然后只改变宽度就行, width += offset; 改变之后view刷新,draw的时候根据宽度、高度得到新的path画出来 [/quote] 你说的【拉右边,左边顶点不变】我理解,但是我对Qt中类和函数不熟悉,我还是不知道代码怎么写?针对我这个程序,您能不能给详细指导一下。
  • 打赏
  • 举报
回复
冷静忍耐 2016-08-23
引用 2 楼 WindFlowInTheSky 的回复:
[quote=引用 1 楼 u013466477 的回复:] 在多边形的boundingrect,每个方位画一个小正方形,用来拉伸缩放形状大小 当鼠标在某个小正方形点击并拖动,在mouseMove事件中根据offset(offset = nowPt - lastPt)改变多边形大小即可
引用 1 楼 u013466477 的回复:
在多边形的boundingrect,每个方位画一个小正方形,用来拉伸缩放形状大小 当鼠标在某个小正方形点击并拖动,在mouseMove事件中根据offset(offset = nowPt - lastPt)改变多边形大小即可
我在Qt Assist中查看了以下,说 QRectF QPolygonF::boundingRect() const 这个函数返回的是多边形的边界矩形,这个函数的返回值也是QRecfF,我怎么用它和offset结合呢?以下是我的mouseMoveEvent函数: void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) { if (myMode == InsertLine && line != 0) { QLineF newLine(line->line().p1(), mouseEvent->scenePos()); line->setLine(newLine); } else if (myMode == MoveItem) { QGraphicsScene::mouseMoveEvent(mouseEvent); } } 最后,你的头像好酷![/quote] QPainterPath 里面的数据就应该是一个宽度和高度决定的(多边形就根据宽高比例来计算,是一样的),例如: path.moveTo(0, 0); path.lineTo(width*0.5, -height*0.5); path.lineTo(width, 0); path.lineTo(width, height); path.lineTo(width*0.5, height + height*0.5); path.lineTo(0, height); path.lineTo(0, 0); 多边形,路径不变,当你改变宽度或高度路径就会被刷新,形状自然会拉伸 拉伸多少那就根据offset来算,整个过程全要用浮点来算才准 函数的返回值也是QRecfF,我怎么用它和offset结合呢? 假如你拉的是右边,那你的左顶点肯定不变,然后只改变宽度就行, width += offset; 改变之后view刷新,draw的时候根据宽度、高度得到新的path画出来
  • 打赏
  • 举报
回复
晴空飞一鹤 2016-08-23
引用 1 楼 u013466477 的回复:
在多边形的boundingrect,每个方位画一个小正方形,用来拉伸缩放形状大小 当鼠标在某个小正方形点击并拖动,在mouseMove事件中根据offset(offset = nowPt - lastPt)改变多边形大小即可
引用 1 楼 u013466477 的回复:
在多边形的boundingrect,每个方位画一个小正方形,用来拉伸缩放形状大小 当鼠标在某个小正方形点击并拖动,在mouseMove事件中根据offset(offset = nowPt - lastPt)改变多边形大小即可
我在Qt Assist中查看了以下,说 QRectF QPolygonF::boundingRect() const 这个函数返回的是多边形的边界矩形,这个函数的返回值也是QRecfF,我怎么用它和offset结合呢?以下是我的mouseMoveEvent函数: void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) { if (myMode == InsertLine && line != 0) { QLineF newLine(line->line().p1(), mouseEvent->scenePos()); line->setLine(newLine); } else if (myMode == MoveItem) { QGraphicsScene::mouseMoveEvent(mouseEvent); } } 最后,你的头像好酷!
  • 打赏
  • 举报
回复
冷静忍耐 2016-08-23
在多边形的boundingrect,每个方位画一个小正方形,用来拉伸缩放形状大小 当鼠标在某个小正方形点击并拖动,在mouseMove事件中根据offset(offset = nowPt - lastPt)改变多边形大小即可
  • 打赏
  • 举报
回复
相关推荐
发帖
Qt
加入

1.3w+

社区成员

Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
申请成为版主
帖子事件
创建了帖子
2016-08-23 01:30
社区公告
暂无公告