当前位置:   article > 正文

QGraphicsTextItem添加自定义下划线_qtextlayout

qtextlayout

qt中有原生的添加下划线的方式(如下)但这种方式效果可能不是很好.

  1. class XXXXX: public QGraphicsTextItem
  2. {
  3. QTextCharFormat tcf;
  4. tcf.setFontUnderline(true);
  5. tcf.setUnderlineStyle(QTextCharFormat::WaveUnderline);
  6. tcf.setUnderlineColor(QColor("#ffff00"));
  7. QTextCursor cursor = textCursor();
  8. cursor.select(QTextCursor::Document);
  9. cursor.mergeCharFormat(tcf);
  10. cursor.clearSelection();
  11. setTextCursor(cursor);
  12. };

效果如下(黄色波浪线)

我找了一下好像也不能继承然后添加自定义的下划线类型,所以我目前用的方法是在paint函数种绘制(有其他好办法的话,请大神们赐教啊,拜托了)。

可以看到一是相比于原生的效果会好一点(还可以更加细致的再去调整)二是从圆或者三角形能看出是跟着字符变化的,主要是因为我不是只用boundingbox的宽度之类的计算的。不过效果有点不好的地方在于,一是选择文本时这些绘制的下划线无法包含在选中文本内,有点影响观感。二是以上图的a为例,最右边的圆和其上方的字母a没有居中对齐,原因下述。

  1. void CTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  2. {
  3. QTextBlock iterBlock = document()->begin();
  4. int blockHeight = 0;
  5. qreal linespace = textCursor().blockFormat().lineHeight();
  6. while(iterBlock != document()->end())
  7. {
  8. QTextLayout* textLayout = iterBlock.layout();
  9. if(nullptr == textLayout)
  10. {
  11. continue;
  12. }
  13. int lineCount = textLayout->lineCount();
  14. for(int i=0; i<lineCount; i++)
  15. {
  16. QTextLine text = textLayout->lineAt(i);
  17. if(1 == decType)
  18. {
  19. painter->setBrush(Qt::NoBrush);
  20. QPainterPath path = wavePath(&text,i+1,blockHeight);
  21. painter->drawPath(path);
  22. }
  23. else if(2 == decType)
  24. {
  25. QPainterPath lineP = linePath(&text,i+1,blockHeight);
  26. painter->drawPath(lineP);
  27. }
  28. else if(3 == decType)
  29. {
  30. QPainterPath doublelineP = doublelinePath(&text,i+1,blockHeight,DoubleLineOffset);
  31. painter->drawPath(doublelineP);
  32. }
  33. else if(4 == decType)
  34. {
  35. drawCircle(&text,painter,i+1,blockHeight,9,4);
  36. }
  37. else if(5 == decType)
  38. {
  39. painter->setBrush(QColor(230,0,0));
  40. QPainterPath triangleP = trianglePath(&text,i+1,blockHeight,14);
  41. painter->drawPath(triangleP);
  42. }
  43. }
  44. blockHeight += textLayout->boundingRect().height() + linespace;
  45. iterBlock = iterBlock.next();
  46. }
  47. }
  48. void CTextItem::drawCircle(QTextLine* textline, QPainter *painter, const int& lineIndex, const int& blockHeight, int radius, int spacing)
  49. {
  50. QList<QGlyphRun> listGR = textline->glyphRuns();
  51. for(int j=0; j<listGR.count(); j++)
  52. {
  53. QGlyphRun glr = listGR.at(j);
  54. QVector<QPointF> pos = glr.positions();
  55. QPainterPath outPath;
  56. QVector<QPointF> vecCircle;
  57. for(int i=0; i<pos.count(); i++)
  58. {
  59. double nextX = 0;
  60. double xPos = pos.at(i).x();
  61. if(i+1<pos.count())
  62. {
  63. nextX = pos.at(i+1).x();
  64. double diff = nextX - xPos;
  65. if(diff>=2*radius + 2)
  66. {
  67. xPos += ((diff-2*radius)/2);//调整圆的位置使之与字符居中对齐
  68. }
  69. }
  70. QTextFrame* rootFrame = document()->rootFrame();
  71. QTextFrameFormat ffmt = rootFrame->frameFormat();
  72. xPos += ffmt.leftMargin();
  73. double yPos = lineIndex*textline->height()+ffmt.topMargin()+blockHeight;
  74. QPointF newP(xPos,yPos);
  75. vecCircle.append(newP);
  76. QPainterPath outCircle = circularPath(newP,radius,0);
  77. outPath.addPath(outCircle);
  78. }
  79. QPen tmp_pen;
  80. tmp_pen.setColor(QColor(230,0,0));
  81. tmp_pen.setWidth(1);
  82. painter->setPen(tmp_pen);
  83. painter->setBrush(Qt::NoBrush);
  84. painter->drawPath(outPath);
  85. painter->setBrush(QColor(230,0,0));
  86. QPainterPath inPath;
  87. for(int i=0; i<vecCircle.count(); i++)
  88. {
  89. QPainterPath inCircle = circularPath(vecCircle.at(i),radius-spacing,spacing);
  90. inPath.addPath(inCircle);
  91. }
  92. painter->drawPath(inPath);
  93. }
  94. }

主要代码在于

    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等相关内容。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/292710
推荐阅读
相关标签
  

闽ICP备14008679号