3

我正在使用 QPainter 在 QImage 上绘制多行文本。但是,我还需要在每个字符的边界框周围显示一个彩色矩形。

所以我需要知道每个角色在绘制时的边界框。

例如,对于

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

考虑到换行符、自动换行、制表符等,我需要得到 10 个矩形。

例如,第二个'l'的矩形将在第一个的矩形下方'l',而不是在 的右侧'e',因为换行符。

类似于这张图片中红色矩形的坐标(我是手工放置的,所以它们并不是真正的正确位置):

在此处输入图像描述

4

2 回答 2

4

这可能不是最好的解决方案,但它是我能想到的最好的解决方案。

我相信你将不得不“自己做”。也就是说,不是绘制一个文本块,而是一次绘制一个字符。然后你可以使用 QFontMetrics 来获取每个字符的边界框。

这是一个小工作,但还不错。类似的东西(伪代码,不是代码):

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

}

查看 QFontMetrics,它有许多不同的方法来获取边界框、最小边界框等。

QFontMetrics 4.7

啊...我现在看到您使用的重载返回实际的边界矩形。如果你愿意,你可以使用它并跳过 QFontMetrics - 否则整体算法是相同的。

于 2012-11-13T18:59:02.190 回答
3

您可以使用 检索单个字符的边界框QFontMetrics::boundingRect(QChar),但它们必须以偏移量(QFontMetrics::ascent从顶部以及QFontMetrics::width从左侧的前面字符)呈现,因为它们是相对于字体的基线而不是相对于底部的完整字符串的边界框。
几行也必须分开处理。 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()});
    }
}

结果是

遗憾的是,这并不完美。

于 2017-11-03T22:25:59.457 回答