没有细化字体的 Qt 轮廓文本 [英] Qt outlined text without thinning font

查看:23
本文介绍了没有细化字体的 Qt 轮廓文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用 Qt4.8 绘制轮廓文本,但我也想保持字体的原始形状和可见性.目前,轮廓隐藏了文本字符,使它们看起来比原件更薄".

I want to draw outlined texts with Qt4.8, but I also want to keep the original shape and visibility of the font. Currently, the outlines hide the text characters and have them look "thinner" than the originals.

Qt 使用 QPen 绘制文本字符(和其他形状)的轮廓.QPen 在字符的实际边缘移动,并在边缘线的外部和内部绘制(请参阅 QPen 参考中的连接样式").

Qt draws outline of text characters (and other shapes) with QPen. QPen moves on the actual edge of a character and paints outside and inside of the edge line (See "Join Style" in QPen reference).

如果您使用较粗的笔,文本字符看起来会较细,而字符占用的总面积会增加轮廓.换句话说,轮廓侵蚀了文本字符.

If you use a thicker pen, a text character looks thinner, while the total area taken by the character increases for the outline. In other words, the outline erodes into the text character.

我想让文本字符保持其原始形状和可见性,同时具有光环效果"的轮廓.即,我只想绘制边缘线的外部.

I want to have text characters keep their original shape and visibility while having "halo effect" from outlining. I.e., I want to paint only the outside of edge lines.

用 Qt 实现这种效果的最简单方法是什么?我想出了一些想法,但我想知道是否有可能.

What is the easiest way to implement such effect with Qt? I came up with a few ideas, but I wonder if any of them is possible.

A 计划

绘制有轮廓的文本,然后在有轮廓的文本上绘制相同的无轮廓文本.

Draw texts with outline, then draw the same texts without outline over the outlined ones.

不幸的是,QTextCursor 不支持过度绘制"或过度打字",而您可以使用经典打字机来实现.也会有性能损失.

Unfortunately, QTextCursor doesn't support "overdrawing" or "overtyping", which you can do with classic typewriters. There would be performance penalty, too.

B 计划

修改Qt库,先用QPen画轮廓,再用QBrush填充.QBrush 将绘制轮廓的内部部分,只保留外部完整.

Modify the Qt library so that it draws outline with QPen first, then fill inside with QBrush. QBrush would paint over the inside part of the outline and leaves only the outside intact.

我不确定它是否有效,如果可能,我想避免修改 Qt 库.

I'm not sure if it works and I want to avoid modifying the Qt library if possible.

C 计划

暂时将用于绘制文本的QPainter的CompositionMode"切换为QPainter::CompositionMode_DestinationOver".

Switch the "CompositionMode" of the QPainter used for drawing text to "QPainter::CompositionMode_DestinationOver" temporarily.

为此,我想我需要控制 Qt 的文本操作小部件(如 QTextBrowser)创建和使用的私有和临时 QPainter,但我不知道如何实现.

To do this, I think I need to control the private and temporary QPainter created and used by Qt's text-manipulation widgets like QTextBrowser, but I don't know how it can be done.

我是 Qt 编程的新手,我在 X 窗口上使用 Qt 4.8.2.

I'm new to Qt programming and I use Qt 4.8.2 on X window.

你可以通过在/usr/lib64/qt4/examples/richtext/calendar/mainwindow.cpp中添加以下代码行(第156-164行),编译并运行它,并将字体大小增加到40来查看我的问题或更大.

You can see my problem by adding the following code lines (line 156-164) to /usr/lib64/qt4/examples/richtext/calendar/mainwindow.cpp, compiling and running it, and increasing the font size to 40 or larger.

 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

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

If you can tell me the way to go and give me the initial clues, I'll appreciate your help very much.

推荐答案

我找到了一种方法,如何为 QGraphicsView 文本对象做这样的大纲.我认为,您可以将它用于任何基于 QTextDocument(例如,QTextEdit)的类.我创建了一个基于 QGraphicsTextItem 的类并重新实现了它的 paint 函数:

I've found a way, how to do such outlining for QGraphicsView text objects. I think, you can use it for any class based on QTextDocument (QTextEdit, for example). I've created a class based on QGraphicsTextItem and reimplemented its paint function:

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

我注意到此解决方案的唯一错误 - 当您编辑文本并开始选择一些字母时,会发生剪切.但这几乎是不可察觉的.对于不可编辑的项目,我找不到任何错误.

The only bug I've noticed for this solution - when you edit text and start selecting some letters, clipping occurs. But it's almost unnoticeable. For non-editable items I can't find any bugs.

但是如果你想勾勒QPushButton文本(例如),那么它是微不足道的(这个问题已经讨论过很多次了)——里面重新实现了paintEvent create QPainterPath,调用path.addText,然后使用painter.strokePathpainter.fillPath - strokePath 创建轮廓,fillPath 填充前景.

But if you want to outline QPushButton text (for example), then it is trivial (this problem has been discussed many times) - inside reimplemented paintEvent create QPainterPath, call path.addText, then use painter.strokePath, painter.fillPath - strokePath creates outline, and fillPath fills foreground.

这篇关于没有细化字体的 Qt 轮廓文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆