2

Here's a very basic piece of code which:

  1. Measures the size a piece of text would take.
  2. Draws the rectangle which corresponds to this size at coordinates (100, 25).
  3. Displays text at coordinates (100, 25).
auto str = "Hello, World!";
auto metrix = window->fontMetrics();
auto text = scene->addText(str);
text->setPos(100, 25);
text->setDefaultTextColor(Qt::white);

auto r = metrix.boundingRect(str);
int x, y, w, h;
r.getRect(&x, &y, &w, &h);
scene->addRect(100, 25, w, h, QPen(Qt::white));

The scene in code is a QGraphicsScene with no specific customizations, with the exception of a border set to zero.

I would expect the text to be exactly inside the rectangle. The text is however shifted by a few pixels to the left and a few more pixels to the bottom. Why?

enter image description here

Arseni Mourzenko
  • 50,338
  • 35
  • 112
  • 199
  • @drescherjm: I should have specified that the text is drawn on a `QGraphicsScene`. If I understand correctly, there are no actual limits for the text, i.e. it may not display entirely on the scene, but there shouldn't be word wrapping or anything like that. – Arseni Mourzenko Oct 15 '20 at 19:49

2 Answers2

3

Solution

Setting the document margins to 0, as @NgocMinhNguyen suggested, might seem to work, but it is not a real solution, because you lose the margins. It would be better, if you could get the actual geometry, including margins etc. For that purpose you can use QGraphicsTextItem::boundingRect() instead of QFontMetrics::boundingRect.

Example

Here is a minimal and complete example I have written for you, in order to demonstrate the proposed solution:

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QBoxLayout>

struct MainWindow : public QWidget
{
    MainWindow(QWidget *parent = nullptr) : QWidget(parent) {
        QPointF p(100, 25);
        auto *l = new QVBoxLayout(this);
        auto *view = new QGraphicsView(this);
        auto *textItem = new QGraphicsTextItem(tr("HHHHHHHH"));
        auto *rectItem = new QGraphicsRectItem(textItem->boundingRect()
                                               .adjusted(0, 0, -1, -1));

        textItem->setPos(p);
        rectItem->setPos(p);

        view->setScene(new QGraphicsScene(this));
        view->scene()->addItem(textItem);
        view->scene()->addItem(rectItem);

        l->addWidget(view);

        resize(300, 300);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

Note: Please note how I create the rectangle. There is a difference between

auto *item = new QGraphicsRectItem(100, 25, w, h);

and

auto *item = new QGraphicsRectItem(0, 0, w, h);
item->setPos(100, 25);

Result

This example produces the following result:

Text in a bounding rectangle

scopchanov
  • 7,966
  • 10
  • 40
  • 68
2

QGraphicsTextItem is held by QTextDocument, which can have a margin.
Setting the margin to 0 and the rectangle will be correctly drawn.

text->document()->setDocumentMargin(0);
Minh
  • 1,630
  • 1
  • 8
  • 18