赞
踩
qt中有原生的添加下划线的方式(如下)但这种方式效果可能不是很好.
- class XXXXX: public QGraphicsTextItem
- {
- QTextCharFormat tcf;
- tcf.setFontUnderline(true);
- tcf.setUnderlineStyle(QTextCharFormat::WaveUnderline);
- tcf.setUnderlineColor(QColor("#ffff00"));
- QTextCursor cursor = textCursor();
- cursor.select(QTextCursor::Document);
- cursor.mergeCharFormat(tcf);
- cursor.clearSelection();
- setTextCursor(cursor);
- };
效果如下(黄色波浪线)
我找了一下好像也不能继承然后添加自定义的下划线类型,所以我目前用的方法是在paint函数种绘制(有其他好办法的话,请大神们赐教啊,拜托了)。
可以看到一是相比于原生的效果会好一点(还可以更加细致的再去调整)二是从圆或者三角形能看出是跟着字符变化的,主要是因为我不是只用boundingbox的宽度之类的计算的。不过效果有点不好的地方在于,一是选择文本时这些绘制的下划线无法包含在选中文本内,有点影响观感。二是以上图的a为例,最右边的圆和其上方的字母a没有居中对齐,原因下述。
- void CTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
- {
- QTextBlock iterBlock = document()->begin();
- int blockHeight = 0;
- qreal linespace = textCursor().blockFormat().lineHeight();
- while(iterBlock != document()->end())
- {
- QTextLayout* textLayout = iterBlock.layout();
- if(nullptr == textLayout)
- {
- continue;
- }
- int lineCount = textLayout->lineCount();
- for(int i=0; i<lineCount; i++)
- {
- QTextLine text = textLayout->lineAt(i);
- if(1 == decType)
- {
- painter->setBrush(Qt::NoBrush);
- QPainterPath path = wavePath(&text,i+1,blockHeight);
- painter->drawPath(path);
- }
- else if(2 == decType)
- {
- QPainterPath lineP = linePath(&text,i+1,blockHeight);
- painter->drawPath(lineP);
- }
- else if(3 == decType)
- {
- QPainterPath doublelineP = doublelinePath(&text,i+1,blockHeight,DoubleLineOffset);
- painter->drawPath(doublelineP);
- }
- else if(4 == decType)
- {
- drawCircle(&text,painter,i+1,blockHeight,9,4);
- }
- else if(5 == decType)
- {
- painter->setBrush(QColor(230,0,0));
- QPainterPath triangleP = trianglePath(&text,i+1,blockHeight,14);
- painter->drawPath(triangleP);
- }
- }
- blockHeight += textLayout->boundingRect().height() + linespace;
- iterBlock = iterBlock.next();
- }
- }
-
- void CTextItem::drawCircle(QTextLine* textline, QPainter *painter, const int& lineIndex, const int& blockHeight, int radius, int spacing)
- {
- QList<QGlyphRun> listGR = textline->glyphRuns();
- for(int j=0; j<listGR.count(); j++)
- {
- QGlyphRun glr = listGR.at(j);
- QVector<QPointF> pos = glr.positions();
- QPainterPath outPath;
- QVector<QPointF> vecCircle;
- for(int i=0; i<pos.count(); i++)
- {
- double nextX = 0;
- double xPos = pos.at(i).x();
- if(i+1<pos.count())
- {
- nextX = pos.at(i+1).x();
- double diff = nextX - xPos;
- if(diff>=2*radius + 2)
- {
- xPos += ((diff-2*radius)/2);//调整圆的位置使之与字符居中对齐
- }
- }
- QTextFrame* rootFrame = document()->rootFrame();
- QTextFrameFormat ffmt = rootFrame->frameFormat();
- xPos += ffmt.leftMargin();
- double yPos = lineIndex*textline->height()+ffmt.topMargin()+blockHeight;
- QPointF newP(xPos,yPos);
- vecCircle.append(newP);
- QPainterPath outCircle = circularPath(newP,radius,0);
- outPath.addPath(outCircle);
- }
- QPen tmp_pen;
- tmp_pen.setColor(QColor(230,0,0));
- tmp_pen.setWidth(1);
- painter->setPen(tmp_pen);
- painter->setBrush(Qt::NoBrush);
- painter->drawPath(outPath);
-
- painter->setBrush(QColor(230,0,0));
- QPainterPath inPath;
- for(int i=0; i<vecCircle.count(); i++)
- {
- QPainterPath inCircle = circularPath(vecCircle.at(i),radius-spacing,spacing);
- inPath.addPath(inCircle);
- }
- painter->drawPath(inPath);
- }
- }
主要代码在于
QList<QGlyphRun> listGR = textline->glyphRuns();
for(int j=0; j<listGR.count(); j++)
{
QGlyphRun glr = listGR.at(j);
QVector<QPointF> pos = glr.positions();
}
这个就可以获取每个字符的位置,据此可以实现下划线根据字符的多少而变化。但同时这里无法获取字符的宽度,所以我是根据前后两个位置差算宽度的,也因此最后一个字符无法计算(上述最右边的字母a)还请大神们赐教啊。
另外就是再加上行高,边距之类的。大家可以去研究一下QTextBlock、QTextLayout、QTextLine等相关内容。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。