6

我想用 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

如果您能告诉我要走的路并给我初步线索,我将非常感谢您的帮助。

4

1 回答 1

2

我找到了一种方法,如何为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文本(例如),那么它是微不足道的(这个问题已经讨论过很多次了) - 内部重新实现paintEventcreate QPainterPath, call path.addText,然后 use painter.strokePathpainter.fillPath-strokePath创建轮廓,并fillPath填充前景。

于 2013-07-07T23:39:29.580 回答