没有细化字体的 Qt 轮廓文本
Posted
技术标签:
【中文标题】没有细化字体的 Qt 轮廓文本【英文标题】:Qt outlined text without thinning font 【发布时间】:2012-12-20 07:03:09 【问题描述】:我想用 Qt4.8 绘制轮廓文本,但我也想保持字体的原始形状和可见性。 目前,轮廓隐藏了文本字符,使它们看起来比原始字符“更薄”。
Qt 使用 QPen 绘制文本字符(和其他形状)的轮廓。 QPen 在角色的实际边缘上移动并在边缘线的外部和内部进行绘制(请参阅 QPen 参考中的“连接样式”)。
如果您使用较粗的钢笔,文本字符会显得较细,而轮廓所占用的总面积会增加。 换句话说,轮廓侵蚀到文本字符中。
我想让文本字符保持其原始形状和可见性,同时从轮廓中获得“光环效果”。 即,我只想绘制边缘线的外侧。
用 Qt 实现这种效果的最简单方法是什么? 我想出了一些想法,但我想知道它们是否可行。
A计划。
画出带轮廓的文字,然后在有轮廓的文字上画出相同的没有轮廓的文字。
不幸的是,QTextCursor 不支持“过度绘制”或“过度打字”,您可以使用经典打字机做到这一点。 也会有性能损失。
B 计划。
修改 Qt 库,使其先用 QPen 绘制轮廓,然后用 QBrush 填充内部。 QBrush 会在轮廓的内部进行绘制,而只保留外部。
我不确定它是否有效,我想尽可能避免修改 Qt 库。
C 计划。
将用于绘制文本的QPainter的“CompositionMode”暂时切换为“QPainter::CompositionMode_DestinationOver”。
为此,我认为我需要控制由 Qt 的文本操作小部件(如 QTextBrowser)创建和使用的私有和临时 QPainter,但我不知道如何做到这一点。
我是 Qt 编程新手,我在 X 窗口上使用 Qt 4.8.2。
您可以通过将以下代码行(第 156-164 行)添加到 /usr/lib64/qt4/examples/richtext/calendar/mainwindow.cpp,编译并运行它,并将字体大小增加到 40 来查看我的问题或更大。
QTextCharFormat format = cursor.charFormat();
format.setFontPointSize(fontSize);
QTextCharFormat boldFormat = format;
boldFormat.setFontWeight(QFont::Bold);
// Additional code lines for green outline : line 156
QPen pen;
pen.setStyle(Qt::SolidLine);
pen.setWidthF(4);
pen.setBrush(Qt::green);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
boldFormat.setTextOutline(pen);
// The end of the additional code : line 164
如果你能告诉我要走的路并给我初步的线索,我将非常感谢你的帮助。
【问题讨论】:
感谢 Ian Atkin,我研究了“Painter Paths”示例并开始认为我的 B 和 C 计划与 Qt 的基本设计背道而驰。使用“奇偶”填充规则,使用 QPen 仅绘制边缘线的外侧并使用 QBrush 填充内侧会产生“星形”和“重叠方形和圆形”示例的丑陋结果。 @Tapa,我已经把这个问题留了很长时间,我没有时间重新审视它(我被另一个项目淹没了)。对于我的延迟回复,我感到非常抱歉。而且,是的,我的一位同事以与您的解决方案非常相似的方式解决了这个问题。我接受你的回答作为我问题的答案。非常感谢。 【参考方案1】:我找到了一种方法,如何为QGraphicsView
文本对象进行这样的概述。我认为,您可以将它用于任何基于QTextDocument
(例如QTextEdit
)的类。我创建了一个基于QGraphicsTextItem
的类并重新实现了它的paint
函数:
void paint (QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
QTextCharFormat format;
format.setTextOutline (QPen (Qt::white, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); // Color and width of outline
QTextCursor cursor (this->document());
cursor.select (QTextCursor::Document);
cursor.mergeCharFormat (format);
QGraphicsTextItem::paint (painter, option, widget);
format.setTextOutline (QPen (Qt::transparent));
cursor.mergeCharFormat (format);
QGraphicsTextItem::paint (painter, option, widget);
我注意到此解决方案的唯一错误 - 当您编辑文本并开始选择一些字母时,会发生剪切。但这几乎是不明显的。对于不可编辑的项目,我找不到任何错误。
但是如果你想勾勒出QPushButton
的文字(例如),那就小菜一碟了(这个问题已经讨论过很多次了)——里面重新实现paintEvent
创建QPainterPath
,调用path.addText
,然后使用@ 987654331@, painter.fillPath
- strokePath
创建轮廓,fillPath
填充前景。
【讨论】:
以上是关于没有细化字体的 Qt 轮廓文本的主要内容,如果未能解决你的问题,请参考以下文章