简体   繁体   English

QPainter :: drawText,为每个角色获取边界框

[英]QPainter::drawText, get bounding boxes for each character

I'm using QPainter to draw multiline text on QImage. 我正在使用QPainter在QImage上绘制多行文字。 However, I also need to display a colored rectangle around each character's bounding box. 但是,我还需要在每个角色的边界框周围显示一个彩色矩形。

So I need to know the bounding box that each character had when being drawn. 所以我需要知道每个角色在绘制时的边界框。

For example, for 例如,对于

painter.drawText(QRect(100, 100, 200, 200), Qt::TextWordWrap, "line\nline2", &r);

I would need to get 10 rectangles, taking into account newlines, word-wrap, tabs, etc. 我需要获得10个矩形,考虑换行,自动换行,制表符等。

For example, the rectangle of the second 'l' would be below the rectangle of the first 'l' , instead of being to the right of 'e' , because of the newline. 例如,由于换行符,第二个'l'的矩形将位于第一个'l'的矩形下方,而不是'e'的右侧。

Something like the coordinates of the red rectangles in this picture (I've put them by hand so they're not really the correct positions): 像这张照片中红色矩形的坐标(我把它们放在手边,所以它们不是真正的正确位置):

在此输入图像描述

This may not be the best solution, but it's the best one I can think of. 这可能不是最好的解决方案,但它是我能想到的最好的解决方案。

I believe you will have to "do it yourself". 我相信你必须“自己动手”。 That is, instead of drawing a block of text, draw each character one at a time. 也就是说,不是绘制文本块,而是一次绘制一个字符。 Then you can use QFontMetrics to get the bounding box of each character. 然后,您可以使用QFontMetrics获取每个角色的边界框。

It's a little work, but not too bad. 这是一个小工作,但不是太糟糕。 Something like (pseudo code, not code): 像(伪代码,而不是代码):

QFontMetrics fm(myFont, paintDevice);
int x = startX;
int y = startY;
for (unsigned int i = 0; i < numChars; i++)
{
    char myChar = mystr[i];  // get character to print/bound
    QRect rect = fm.boundingRect( myChar );   // get that char's bounding box
    painter.drawText(x, y, Qt::TextWordWrap, mystr[i], &r);  // output char
    painter.drawRect(...); // draw char's bounding box using 'rect'
    x += rect.width();     // advance current position horizontally

    // TODO:
    // if y > lineLen      // handle cr
    //     x = startX;
    //     y += line height

}

Check out QFontMetrics, it has a number of different methods for getting bounding boxes, minimum bounding boxes, etc. 查看QFontMetrics,它有许多不同的方法来获取边界框,最小边界框等。

QFontMetrics 4.7 QFontMetrics 4.7

Ahhh... I see now that the overload you're using returns the actual bounding rect. 啊......我现在看到你正在使用的重载返回实际的边界矩形。 You can just use that and skip the QFontMetrics if you like - otherwise the overall algorithm is the same. 如果您愿意,您可以使用它并跳过QFontMetrics - 否则整体算法是相同的。

You can retrieve the bounding boxes of individual characters with QFontMetrics::boundingRect(QChar) , but they have to be rendered at an offset ( QFontMetrics::ascent from the top as well as QFontMetrics::width of the preceding characters from the left) because they are relative to the font's base line and not to the bottom of the bounding box of the complete string. 您可以使用QFontMetrics::boundingRect(QChar)检索单个字符的边界框,但它们必须以偏移量( QFontMetrics::ascent以及左边前面字符的QFontMetrics::width呈现因为它们是相对于字体的基线而不是相对于完整字符串的边界框的底部。
Several lines also have to be handled separately. 还必须单独处理几行。 QFontMetrics::lineSpacing give you their offset. QFontMetrics::lineSpacing为您提供偏移量。

QPainter painter(this);
painter.setFont(QFont("Arial", 72));

auto pen = painter.pen();

QString text{"line\nline2\ngg\n`"};
QRect boundingRect;
painter.drawText(rect(), Qt::AlignLeft | Qt::AlignTop, text, &boundingRect);
painter.drawRect(boundingRect.adjusted(0, 0, -pen.width(), -pen.width()));

pen.setColor(Qt::red);
painter.setPen(pen);
const auto lines = text.split('\n');
const auto fm = painter.fontMetrics();
for (int linei = 0; linei < lines.size(); ++linei) {
    const auto & line = lines[linei];
    for (int chi = 0; chi < line.size(); ++chi) {
        const auto bounds = fm.boundingRect(line[chi]);
        const auto xoffset = bounds.x() + fm.width(line, chi);
        const auto lineOffset = linei * fm.lineSpacing() + fm.ascent();
        const auto yoffset = lineOffset + bounds.y();
        painter.drawRect(QRect{xoffset, yoffset, bounds.width(), bounds.height()});
    }
}

results in 结果是

which, sadly – isn't perfect though. 遗憾的是,这并不完美。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM