我想创建一个简单的图形场景(子类为QGraphicsScene):
这就是我想要做的:
蓝色框的尺寸是动态的,箭头和标签也可能绘制在不同的位置。 sceneRect()定义了一个与一个变量(基本上是蓝色框的高度)有关的坐标系。
我可以在预期的位置绘制矩形和线条,但是当我为标签添加QGraphicsSimpleTextItem时,无法正确定位它。
我创建了simpleTextItem,将其添加到场景中,然后测量它的宽度和高度(使用boundingRect()),以像素为单位提供w / h。然后,我尝试使用mapRectToScene()将宽度和高度转换为场景坐标,但没有得到我期望的结果。我得到的像素值相同。
我在调试器中查看了所有item-> mapRectTo / From方法的结果,似乎没有什么能给我我所期望的。每个方法都从文本项返回未转换的boundingRect。
我应该怎么做才能为label-> setPos()获取适当的偏移量(在场景坐标中),以在我想要的位置(箭头的左侧,与箭头的中间水平对齐)获取标签? ??
void MyGraphicsScene::updateScene()
{
// Setup is that "thickness_" is a variable and the scene coordinate system
// is set up around this value. In my testing I have thickness_ = 1.0, so the
// coordinate system is -1.5 to 1.5 in X and Y.
//
// Scene rect centered at 0,0
// setSceneRect(-1.5*thickness_, -1.5*thickness_, 3.0*thickness_, 3.0*thickness_);
clear();
QColor bkgColor("#888888");
setBackgroundBrush(QBrush(bkgColor));
double centX = 0.0;
double centY = 0.0;
double boxLeft = centX - thickness_/2.0;
double boxRight = centX + thickness_/2.0;
double boxTop = centY - thickness_/2.0;
double boxBot = centY + thickness_/2.0;
// The sample volume cross-section as a light blue box
QColor boxColor("lightblue");
QColor lineColor("black");
QBrush boxBrush(boxColor);
QPen boxPen(lineColor);
boxPen.setWidth(1);
boxPen.setCosmetic(true);
QGraphicsRectItem *rect = addRect(boxLeft, boxTop, thickness_, thickness_, boxPen, boxBrush);
// Mid-section line
QPen linePen(lineColor);
linePen.setWidth(3);
linePen.setCosmetic(true);
QGraphicsLineItem *line = addLine(boxLeft, centY, boxRight, centY, linePen);
// Draw a position arrow
double y = centY;
QColor arrowColor("red");
QPen arrowPen(arrowColor);
arrowPen.setWidth(3);
arrowPen.setCosmetic(true);
double arrowLength = 0.2*thickness_;
QGraphicsLineItem *arrowLine = addLine(centX - thickness_/2.0 - arrowLength, y,
centX - thickness_/2.0, y, arrowPen);
// Arrowhead
line = addLine(boxLeft - arrowLength*.1, y - (0.3*zStep_), boxLeft, y, arrowPen);
line = addLine(boxLeft - arrowLength*.1, y + (0.3*zStep_), boxLeft, y, arrowPen);
// All works as expected until I try to create and place the label...
// Arrow Label
QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem("Focus");
label->setBrush(QColor("black"));
label->font().setBold(true);
label->setFlag(QGraphicsItem::ItemIgnoresTransformations);
addItem(label);
// Measure the size of the SimpleTextItem (gives me a rect in pixels the size of the text string: 43w 18h)
QRectF itemBR = label->boundingRect();
// I expect this to be in "scene" coordinates so width and height are pixels transformed to scene space
QRectF itemSceneBR = label->mapRectToScene(itemBR); // But it is the same as itemBR...
// Set the position of the label to the left of the arrow, offset Y to align with middle of line
double offsetX = itemSceneBR.width(); // = 43.0... no transform done
double offsetY = itemSceneBR.height()*0.5; // = 9.0... no transform done
// Empirically, I expect about this in scene coordinates:
offsetX = 0.6;
offsetY = 0.12;
label->setPos(boxLeft - arrowLength - offsetX, y - offsetY);
QGraphicsView *theView = (QGraphicsView *)views().at(0);
theView->fitInView(sceneRect(), Qt::KeepAspectRatio);
}
新信息: 通过使用以下方法将textItem boundingRect(上面的代码中的itemBR)的宽度和高度转换为场景坐标,可以解决此问题:
double GrTestMain::scaleFromPixels(QGraphicsView *theView, int
pixelDimension, bool isHorizontal)
{
double length = 0.0;
if(isHorizontal)
{
length = pixelDimension / qAbs(theView->viewportTransform().m11());
}
else
{
length = pixelDimension / qAbs(theView->viewportTransform().m22());
}
return length;
}
我不太喜欢这种解决方案,但是可以。似乎应该更容易一些,但是我尝试将QGraphicsSimpleTextItem转换为场景坐标的任何方法(item-> mapRectTo ...()等)都没有达到我的期望。