使用非默认sceneRect

时间:2019-04-09 20:39:37

标签: c++ qt qgraphicsscene qgraphicssimpletextitem

我想创建一个简单的图形场景(子类为QGraphicsScene):

这就是我想要做的:

enter image description here

蓝色框的尺寸是动态的,箭头和标签也可能绘制在不同的位置。 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 ...()等)都没有达到我的期望。

0 个答案:

没有答案