4

My strategy when centering text on images is to get bounding rectangle for that text and divide width or height by two. I did the same in this case. This is example I have created:

void CanvasWidget::paintEvent(QPaintEvent*)
{
    //Create image:
    QImage image(rect().width(), rect().height(), QImage::Format_RGB32);
    QPainter paint(&image);
    // White background
    image.fill(QColor("#FFF"));
    // set some metrics, position and the text to draw
    QFontMetrics metrics = paint.fontMetrics();
    int yposition = 100;
    QString text = "Hello world.";
    // Draw gray line to easily see if centering worked
    paint.setPen(QPen(QColor("#666"), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
    paint.drawLine(0, yposition, image.width(), yposition);
    // Get rectangle
    QRect fontRect = metrics.boundingRect(text);
    // Black text
    paint.setPen(QPen(QColor("#000"), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
    // Add half the height to position (note that Qt has [0,0] coordinates at the bottom of the image
    paint.drawText(4, yposition+round(((double)fontRect.height())/2.0), text);


    QPainter p(this);
    p.drawImage(rect(), image, image.rect());
    p.end();
}

This is the result - the text is under line instead centered on the line:

Android:
image description
Windows:
image description

I used lines to draw frame around the text based on metrics rectangle:

image description

Intended result was to center visible text exactly around the given point/line:

image description

To put you in perspective, this is the actual problem I am having:
image description
The numbers should be in the middle of the lines, not so much below.

The function I am using returns size including accents and other big characters that aren't there. How do I get the rectangle in pixels only for characters that are there?

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778

1 Answers1

2

Not quite sure what you're asking, but if it's why does the bounding rect appear wrong, it's because you're not taking into account characters that have accents in the font such as é, å etc. The bounding rect returned from font metrics includes these.

As it states in the boundingRect documentation

The height of the bounding rectangle is at least as large as the value returned by height().

This is not the case for tightBoundingRect that will, I expect, provide the right result.

TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
  • I will try it. But I wonder - I posted full working code, image of wrong and correct (expected) result. What else is that I could do to make the topic more clear? Or what was unclear? – Tomáš Zato Jan 13 '16 at 11:06
  • The heading of the question suggests that the text is to be drawn vertically, not horizontally. The result of what you're seeing includes a phone's status bar that detracts from the problem and the difference between what you're seeing and the intended result is very subtle, so the addition of a description of the difference would have helped. If I were to have posed the question, I would have asked *"Why does the bounding rect extend above the pixels of the visible characters?"* – TheDarkKnight Jan 13 '16 at 11:14
  • But I know why the rectangle extends, what I needed is the correct solution. I will try to improve the question. – Tomáš Zato Jan 13 '16 at 11:20
  • Ok, but the question did not demonstrate that you were aware of the reason of the height of the rectangle. In this case I suggest that stating the following would be an improvement *"As the returned bounding rectangle extends above the characters, to account for accents in the font, what method would provide a bounding rectangle just for the visible text?"* – TheDarkKnight Jan 13 '16 at 11:23
  • I improved the question. I also tested tightBoundingRect and it seems to be working. – Tomáš Zato Jan 13 '16 at 11:36