QPainter :: drawText, получить ограничивающие рамки для каждого символа

Я использую QPainter для рисования многострочного текста на QImage. Тем не менее, мне также нужно отобразить цветной прямоугольник вокруг ограничительной рамки каждого персонажа.

Поэтому мне нужно знать ограничивающую рамку, которая была у каждого персонажа при рисовании.

Например, для

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

Мне нужно было бы получить 10 прямоугольников, учитывая переводы строк, перенос слов, вкладки и т. Д.

Например, прямоугольник второго 'l' будет ниже прямоугольника первого 'l'вместо того, чтобы быть справа от 'e'из-за перевода строки.

Что-то вроде координат красных прямоугольников на этом рисунке (я поставил их вручную, чтобы они не были в правильном положении):

введите описание изображения здесь

2

Решение

Возможно, это не лучшее решение, но это лучшее, что я могу придумать.

Я верю, что вам придется «сделать это самостоятельно». То есть вместо того, чтобы рисовать блок текста, рисуйте каждый символ по одному. Затем вы можете использовать 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, если хотите — в противном случае общий алгоритм такой же.

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()});
}
}

результаты в


что, к сожалению — не идеально, хотя.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector