Я хочу создать простую графическую сцену (в подклассе QGraphicsScene):
Вот что я пытаюсь сделать:
Размеры синего прямоугольника являются динамическими, и стрелка и метка также могут быть нарисованы в разных местах. SceneRect () определяет систему координат относительно одной переменной (по сути, высоты синего прямоугольника).
Я могу нарисовать прямоугольник и линии в ожидаемых местах, но когда я добавляю QGraphicsSimpleTextItem для метки, я не могу правильно расположить его.
Я создаю simpleTextItem, добавляю его в сцену, затем измеряю его ширину и высоту (используя boundingRect ()), который дает мне ш / ч в пикселях. Затем я пытаюсь преобразовать эту ширину и высоту в координаты сцены, используя 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 ... () и т. Д.), Не дал мне того, что я ожидал.