Tha*_*lia 6 qt qtextdocument qgraphicstextitem
我需要创建具有文本内容的确切宽度和高度的文本项.
文本的高度是最重要的要求.
文本的位置应该与文本本身相关.
我还必须能够将它放在画布上的确切位置.
假设一个(可打印的)画布(在一个更大的画布上QGraphicsScene),比如5英寸宽和1英寸高,我的文字应该能够从上下左右拉伸 - 并且放在画布上,而不是部分画出.
我正在QGraphicsTextItem为我的项目类型进行子类化.我正在调整大小,使用QTransform()所需的大小 - 以英寸或毫米或像素(72*英寸)为单位.
同时将document()边距设置为0,内部的任何内容(如QTextBlockFormat边距)也设置为0.
我已经实现了setItemSize(QSizeF sz)(以像素为单位的sz),QGraphicsTextItem根据需要调整大小.
使用项目边界rect初始化sz.
假设没有换行,单行文本(解决此问题后可以单独解决多行).
将项目添加到画布时,我仍然会看到顶部和底部边距 - 这会根据字体选择而有所不同.
我在项目周围画了一个矩形来看它.
顶部/底部距离取决于字体选择.
我曾尝试使用字体指标来确定这些距离(paint()我在绘制线条时试图确定文本适合的位置和矩形).
我很乐意至少能够确定用于大写字母,没有重音符号或特殊字符字体的正确大小(这将是一个开始,但自然我需要能够使用任何字符).
但至少有一些方法可以确定文本内容的大小和位置(相对于项目的(0,0)),即使在最简单的情况下......
字体度量tightBoundingRect()似乎是最准确的大小,但似乎无法确定其位置,以便我可以以某种方式正确创建我的项目,并可能正确调整大小/移动它们以适应画布.
以下是我努力确定至少相对于项目的(0,0)的文本的确切大小和位置的一些示例(假设一旦我这样做,我能够将该信息暴露给外部或包括班次在项目转换调整大小).
请注意,字体度量标注的文本大小并不总是覆盖文本,对于不同的字体,我无法在文本本身周围放置紧束缚矩形(洋红色).(我做了多次猜测,下面的代码只有一个 - 这些行试图显示不同的字体指标大小).
以上是继承文本项的绘画功能的实验QGraphicsTextItem:
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
// draw text
QGraphicsTextItem::paint(painter, option, widget);
QPen p;
p.setWidthF(0);
QFontMetricsF fm(this->font());
qreal ascent = fm.ascent(),
descent = fm.descent(),
hheight = fm.height();
QRectF r = QGraphicsTextItem::boundingRect();
QRectF rFont= fm.tightBoundingRect(toPlainText());
qreal xmax = r.right();
painter->save();
painter->setBrush(Qt::NoBrush);
// where is "ascent + descent"
p.setColor(Qt::green);
painter->setPen(p);
painter->drawLine(QPointF(2, ascent), QPointF(2, ascent + descent));
painter->drawLine(QPointF(2, ascent + descent), QPointF(xmax/2, ascent + descent));
// where is "height"
p.setColor(Qt::red);
painter->setPen(p);
painter->drawLine(QPointF(xmax/2, 0), QPointF(xmax/2, hheight));
painter->drawLine(QPointF(xmax/2, ascent + descent), QPointF(xmax, ascent + descent));
// where is "ascent"
p.setColor(Qt::yellow);
painter->setPen(p);
painter->drawLine(QPointF(6, 0), QPointF(6, ascent));
painter->drawLine(QPointF(6, ascent), QPointF(xmax, ascent));
// something that may look like top of the text
p.setColor(Qt::blue);
painter->setPen(p);
qreal yyy = ascent + rFont.y() + 1;
painter->drawLine(QPointF(5, yyy), QPointF(xmax, yyy));
// this should be useful... should be the natural offset
qreal yoffset = (r.height() - rFont.height()) / 2;
// qDebug() << yoffset << r << rFont;
//qreal y0 = (r.height() - fm.height())/2;
p.setColor(Qt::darkGreen);
painter->drawEllipse(10, yoffset, 1, 1);
// where is the font rect
p.setColor(Qt::magenta);
painter->setPen(p);
yoffset = (r.height() + rFont.height()) / 2;
painter->translate(0, yoffset);
painter->drawRect(rFont);
painter->restore();
}
Run Code Online (Sandbox Code Playgroud)
我也尝试不使用QGraphicsTextItem,但在矩形内绘制文本.同样的事情发生了.
(Qt 4.7 - 5.x)
这不是一个好的解决方案。这是尝试解决我自己的问题 - 在第一次迭代中 - 使用字体规格设置给定宽度和高度的文本。
成绩不好的原因——
即使调整大小后,文本也比所需的要小,我不明白为什么
位置不正确,根据字体样式,文本可能位于画布上方或下方,这意味着它会被剪切。
我使用根据项目边界矩形大小和字体度量边界矩形计算的因子来调整它的大小(我使用紧密边界矩形来获得更准确的尺寸)。
myText->setItemFontSize(12); // If I use font metrics I need to reset text size on every change, because resizing loses font info
QFontMetricsF fm(myText->font());
QRectF fmRect = fm.tightBoundingRect(myText.toPlainText().toUpper());
// without toUpper() the size is too small - even so it is a bit small
// I read tightBoundingRect is slow - but boundingRect and height and ascent all give values that result in even smaller size
//qreal absH = fm.ascent();
qreal absH = fmRect.height();
qreal absW = fmRect.width();
qreal absHeightRatio = myText->getItemSize().height() / absH;
qreal absWidthRatio = myText->getItemSize().width() / absW;
Run Code Online (Sandbox Code Playgroud)
然后设置尺寸:
myText->setItemSize(QSizeF(absWidthRatio * textLength, absHeightRatio * fontHeight));
// This function scales the `QTransform` on item
// but since I request a final position dependent on item size
// (including blank space around it) - it has no chance of being accurate.....
// This is where my next effort will go, figuring out how to get rid of the fluff
// around the item inside the scaling
Run Code Online (Sandbox Code Playgroud)
设置位置的函数:尝试居中文本:
// leftShift = 10, rightShift = 10 in example
myText->setPos(0,0);
QRectF r = myText->mapToScene(myText->boundingRect()).boundingRect();
QSizeF sz = r.size();
qreal w = sz.width();
qreal h = sz.height();
qreal cx = (m_docLength - w + leftShift - rightShift)/2 - r.left();
qreal cy = (m_docHeight - h)/2 - r.top();
myText->setPos(cx, cy);
Run Code Online (Sandbox Code Playgroud)
下面的图片适用于 fontHeight = m_docHeight -
理想的:
- 文本的整个大小(上升+下降)等于文档高度,并且文本根据内容垂直居中
- 或者大写大小文本等于文档高度并且下降低于文档(仅基于大写字母居中的文本) ) - 根据QGraphicsTextItem它的定位方式,这看起来会更容易
实际:
-无论我使用哪个参数进行缩放,文本都会更小,并且基于大写文本居中
如上所示 - 我不知道如何根据内容垂直居中(因此对于边到边的文本,下降将适合) - 而取而代之的是,我真正想要的是边到边的大写字母,但我似乎无法实现这一目标。
哦,这些是 Arial 字体——表现最好的字体之一。其他字体在画布上方或下方到处跳跃。对于某些字体,生成的文本实际上更小 - 这对我来说是无法解释的,因为紧密边界矩形怎么可能比项目边界矩形更小......
尽管如此,我还是让我的文本尽可能接近“真实”大小并将其放置在与其大小相匹配的画布上。
| 归档时间: |
|
| 查看次数: |
2470 次 |
| 最近记录: |