Results 1 to 6 of 6

Thread: Setting font has no effect in QGraphicsItem subclass paint() method

  1. #1
    Join Date
    Jun 2008
    Location
    Boulder, Colorado, USA
    Posts
    70
    Thanks
    16
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Setting font has no effect in QGraphicsItem subclass paint() method

    My custom drawing of a QGraphicsItem includes text using user-configurable fonts (previously picked with QFontDialog).

    Attempting to assign the font to either the provided QPainter OR to the QGraphicsScene within my subclass’ QGaphicsItem::paint() method has no effect. The plan is to render a few different text pieces using distinct fonts. Is it possible to do this in QGraphicsItem::paint()? (virtual method override). [See code excerpt below].

    I know I could deploy child QGraphicsTextItems or QGraphicsSimpleTextItems. I will if I have to. (Do I have to?).

    (We're using Qt 4.8.5 on Windows).

    Qt Code:
    1. QFont _labelFont;
    2. const QString labelFontStr = labelFontName();
    3. _labelFont.fromString (labelFontStr);
    4.  
    5. // virtual from QGraphicsItem
    6. void TeacupGfxItem::paint (QPainter* painter,
    7. const QStyleOptionGraphicsItem* /*options*/,
    8. QWidget* /*widget*/ /*=NULL*/)
    9. {
    10. // ... ... ...
    11.  
    12. // *** NEITHER OF THESE HAVE ANY EFFECT ***
    13. painter->setFont (_labelFont);
    14. scene()->setFont (_labelFont);
    15.  
    16. const QString labelStr = teacupLabelStr();
    17. static const int textFlags = Qt::AlignHCenter | Qt::AlignTop |
    18. Qt::TextDontClip | Qt::TextSingleLine;
    19. QRectF drawnBoundRect;
    20. painter->setPen (QPen (Qt::black));
    21. painter->drawText (_labelRect, textFlags, labelStr, &drawnBoundRect);
    22. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,248
    Thanks
    304
    Thanked 867 Times in 854 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Setting font has no effect in QGraphicsItem subclass paint() method

    QFont _labelFont;
    const QString labelFontStr = labelFontName();
    _labelFont.fromString (labelFontStr);
    Where does this code live? Does it just sort of float there in limbo at the top of the file? Is it part of some other method?

    Read the description of QFont::fromString(). Simply passing in the name of the font is not a valid argument, so you are almost certainly ending up with an invalid font instance, which of course will not be used by the painter.

  3. The following user says thank you to d_stranz for this useful post:

    philw (10th September 2014)

  4. #3
    Join Date
    Jun 2008
    Location
    Boulder, Colorado, USA
    Posts
    70
    Thanks
    16
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Setting font has no effect in QGraphicsItem subclass paint() method

    d_stranz, thanks for your reply!

    I am INDEED having a QFont problem, right in the area your response focused on. This is my own application-level mistake ... the string is actually our own generated CSS Font Declaration thingy ... e.g. "font: italic medium 30px Verdana, Helvetica, sans-serif;" ... for which we, unfortunately, don't have a way to generate the original QFont. But the point here is that, nope, I cannot use that string in a call to QFont::fromString (const QString& descrip).

    [Wouldn't in be great to have heuristic CSS font declaration encoding/decoding support in QFont !]

    Sorry about the confusion of the initial disembodied statements. QFont _labelFont (and also QRectF _labelRect) are fields in my QGraphicsItem subclass, and the related statements appear elsewhere in that class.

    To clarify, in fact, Calling QPainter::setFont() within a QGraphicsItem::paint() implementation — with a VALID QFont instance — IS WORKING for me. Thank you.

    I had cross posted on the Qt Project Forum, on which there were also useful responses. SEE: https://qt-project.org/forums/viewthread/47233/

    - Phil

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,248
    Thanks
    304
    Thanked 867 Times in 854 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Setting font has no effect in QGraphicsItem subclass paint() method

    It should not be difficult to parse out the fields in the CSS font declaration, using a combination of QString::split(), a lookup table of known tokens ("italic", "medium", etc.) and font names, and a QRegExp regular expression matcher for the variable bits ("30px"). There are QFont methods to turn each of those into a setting.

    By the way, it is considered dangerous (or at best bad form) to begin variable names with an underscore. Many compiler name-mangling conventions add one or more underscore prefixes and you could unwittingly end up in conflict with an internal variable. Trailing and embedded underscores are fine.

    The comment in the Qt Project post regarding setFont() and drawText() performance isn't valid, in my opinion. At some level, these calls (or the platform-specific equivalent) must be made whenever a font changes and text is painted, so it doesn't matter whether you call them or the internals do (e.g. when painting a QGraphicsTextItem). What will cost a slight performance hit is constructing QFont and other instances within the paint() methods. If these can be constructed once and then simply used within paint() then you avoid that overhead.
    Last edited by d_stranz; 10th September 2014 at 22:54.

  6. The following user says thank you to d_stranz for this useful post:

    philw (13th September 2014)

  7. #5
    Join Date
    Jun 2008
    Location
    Boulder, Colorado, USA
    Posts
    70
    Thanks
    16
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Setting font has no effect in QGraphicsItem subclass paint() method

    Below is my generally successful attempt at basic QFont / CSS font specification encoding/decoding functions. (d_stranz, thanks for the nudge).

    I did not find a way of providing a list of "fallback" font faces from a QFont or QFontInfo instance. (The QFont::substitutes() method apparently doesn’t do that). This is not a problem for my current need since I am just trying to round-trip a QFont created with QFontDialog through a CSS font spec serialization. But for more general use, it sure would be great to get fallback font faces into the CSS font spec. Any ideas?

    Short of that, is there a general way to determine if a given QFont is a serif or sans-serif font?

    Below are my header file and the two separate methods in a HtmlCssUtils namespace:

    Qt Code:
    1. // File: HtmlCssUtils.hpp
    2.  
    3. #pragma once
    4. #ifndef HtmlCssUtilsINCLUDED
    5. #define HtmlCssUtilsINCLUDED
    6.  
    7. #include <QString>
    8. #include <QFont>
    9.  
    10. namespace HtmlCssUtils
    11. {
    12. QString encodeCssFont (const QFont& refFont);
    13. QFont decodeCssFontString (const QString& cssFontStr);
    14. }
    15.  
    16. #endif
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. // File: HtmlCssUtils.cpp
    2.  
    3. #include "HtmlCssUtils.hpp"
    4. #include <QList>
    5. #include <QStringList>
    6.  
    7. QString HtmlCssUtils::encodeCssFont (const QFont& refFont)
    8. {
    9. //-----------------------------------------------------------------------
    10. // This function assembles a CSS Font specification string from a QFont.
    11. // This supports most of the QFont attributes settable in the Qt 4.8 and
    12. // Qt 5.3 QFontDialog.
    13. //
    14. // (1) Font Family
    15. // (2) Font Weight (just bold or not)
    16. // (3) Font Style (possibly Italic or Oblique)
    17. // (4) Font Size (in either pixels or points)
    18. // (5) Decorations (possibly Underline or Strikeout)
    19. //
    20. // Not supported: Writing System (e.g. Latin).
    21. //
    22. // See the corresponding decode function, below.
    23. // QFont decodeCssFontString (const QString cssFontStr)
    24. //-----------------------------------------------------------------------
    25.  
    26. QStringList fields; // CSS font attribute fields
    27.  
    28. // ***************************************************
    29. // *** (1) Font Family: Primary plus Substitutes ***
    30. // ***************************************************
    31.  
    32. const QString family = refFont.family();
    33.  
    34. // NOTE [9-2014, Qt 4.8.6]: This isn't what I thought it was. It
    35. // does not return a list of "fallback" font faces (e.g. Georgia,
    36. // Serif for "Times New Roman"). In my testing, this is always
    37. // returning an empty list.
    38. //
    39. QStringList famSubs = QFont::substitutes (family);
    40.  
    41. if (!famSubs.contains (family))
    42. famSubs.prepend (family);
    43.  
    44. static const QChar DBL_QUOT ('"');
    45. const int famCnt = famSubs.count();
    46. QStringList famList;
    47. for (int inx = 0; inx < famCnt; ++inx)
    48. {
    49. // Place double quotes around family names having space characters,
    50. // but only if double quotes are not already there.
    51. //
    52. const QString fam = famSubs [inx];
    53. if (fam.contains (' ') && !fam.startsWith (DBL_QUOT))
    54. famList << (DBL_QUOT + fam + DBL_QUOT);
    55. else
    56. famList << fam;
    57. }
    58.  
    59. const QString famStr = QString ("font-family: ") + famList.join (", ");
    60. fields << famStr;
    61.  
    62. // **************************************
    63. // *** (2) Font Weight: Bold or Not ***
    64. // **************************************
    65.  
    66. const bool bold = refFont.bold();
    67. if (bold)
    68. fields << "font-weight: bold";
    69.  
    70. // ****************************************************
    71. // *** (3) Font Style: possibly Italic or Oblique ***
    72. // ****************************************************
    73.  
    74. const QFont::Style style = refFont.style();
    75. switch (style)
    76. {
    77. case QFont::StyleNormal: break;
    78. case QFont::StyleItalic: fields << "font-style: italic"; break;
    79. case QFont::StyleOblique: fields << "font-style: oblique"; break;
    80. }
    81.  
    82. // ************************************************
    83. // *** (4) Font Size: either Pixels or Points ***
    84. // ************************************************
    85.  
    86. const double sizeInPoints = refFont.pointSizeF(); // <= 0 if not defined.
    87. const int sizeInPixels = refFont.pixelSize(); // <= 0 if not defined.
    88. if (sizeInPoints > 0.0)
    89. fields << QString ("font-size: %1pt") .arg (sizeInPoints);
    90. else if (sizeInPixels > 0)
    91. fields << QString ("font-size: %1px") .arg (sizeInPixels);
    92.  
    93. // ***********************************************
    94. // *** (5) Decorations: Underline, Strikeout ***
    95. // ***********************************************
    96.  
    97. const bool underline = refFont.underline();
    98. const bool strikeOut = refFont.strikeOut();
    99.  
    100. if (underline && strikeOut)
    101. fields << "text-decoration: underline line-through";
    102. else if (underline)
    103. fields << "text-decoration: underline";
    104. else if (strikeOut)
    105. fields << "text-decoration: line-through";
    106.  
    107. const QString cssFontStr = fields.join ("; ");
    108. return cssFontStr;
    109. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. QFont HtmlCssUtils::decodeCssFontString (const QString& cssFontStr)
    2. {
    3. //-----------------------------------------------------------------------
    4. // This function creates a QFont from the provided CSS Font specification
    5. // string. This supports most of the QFont attributes settable in the
    6. // Qt 4.8 and Qt 5.3 QFontDialog.
    7. //
    8. // (1) Font Family
    9. // (2) Font Weight (just bold or not)
    10. // (3) Font Style (possibly Italic or Oblique)
    11. // (4) Font Size (in either pixels or points)
    12. // (5) Decorations (possibly Underline or Strikeout)
    13. //
    14. // Not supported (defaulted): Writing System (e.g. Latin).
    15. //
    16. // See the corresponding encode function, above.
    17. // QString encodeCssFont (const QFont&)
    18. //-----------------------------------------------------------------------
    19.  
    20. QFont retFont;
    21.  
    22. QStringList fields = cssFontStr .split (';');
    23. const int fieldCnt = fields.count();
    24.  
    25. for (int inx = 0; inx < fieldCnt; ++inx)
    26. {
    27. const QString field = fields [inx] .trimmed();
    28. if (field.isEmpty()) continue;
    29. //----------------------------
    30.  
    31. const QStringList keyAndValue = field.split (':');
    32. if (keyAndValue.count() != 2) continue;
    33. //-------------------------------------
    34.  
    35. const QString key = keyAndValue [0] .trimmed() .toLower();
    36. const QString val = keyAndValue [1] .trimmed();
    37. const QString valLower = val .toLower();
    38.  
    39. // *************************
    40. // *** (1) Font Family ***
    41. // *************************
    42.  
    43. if (key .contains ("font-family"))
    44. {
    45. QStringList famList = val.split (',');
    46. if (!famList.isEmpty())
    47. {
    48. // Use only the first family in a comma separated list
    49. QString fam = famList [0] .trimmed();
    50.  
    51. // Remove leading and trailing double quotes
    52. static const QChar DBL_QUOT ('"');
    53. if (fam .startsWith (DBL_QUOT))
    54. fam = fam .mid (1) .trimmed();
    55. if (fam .endsWith (DBL_QUOT))
    56. { fam .chop (1); fam = fam.trimmed(); }
    57.  
    58. if (!fam.isEmpty())
    59. retFont .setFamily (fam);
    60. }
    61. }
    62.  
    63. // ********************************
    64. // *** (2) Font Weight (Bold) ***
    65. // ********************************
    66.  
    67. else if (key .contains ("font-weight"))
    68. {
    69. if (valLower .contains ("bold"))
    70. retFont .setBold (true);
    71. }
    72.  
    73. // ********************************************
    74. // *** (3) Font Style (Italic or Oblique) ***
    75. // ********************************************
    76.  
    77. else if (key .contains ("font-style"))
    78. {
    79. if (valLower .contains ("italic"))
    80. retFont .setStyle (QFont::StyleItalic);
    81. else if (valLower .contains ("oblique"))
    82. retFont .setStyle (QFont::StyleOblique);
    83. }
    84.  
    85. // ************************************************
    86. // *** (4) Font Size: either Pixels or Points ***
    87. // ************************************************
    88.  
    89. else if (key .contains ("font-size"))
    90. {
    91. bool numOk (false);
    92. QString numPart (valLower);
    93. numPart.chop (2);
    94. const double num = numPart.toDouble (&numOk);
    95.  
    96. if (numOk && (num > 0.0))
    97. {
    98. if (valLower.endsWith ("px"))
    99. retFont .setPixelSize (int (num));
    100. else if (valLower.endsWith ("pt"))
    101. retFont .setPointSizeF (num);
    102. }
    103. }
    104.  
    105. // ***********************************************
    106. // *** (5) Decorations: Underline, Strikeout ***
    107. // ***********************************************
    108.  
    109. else if (key .contains ("text-decoration"))
    110. {
    111. if (valLower.contains ("underline"))
    112. retFont .setUnderline (true);
    113. if (valLower.contains ("line-through"))
    114. retFont .setStrikeOut (true);
    115. }
    116.  
    117. } // end for (int inx = 0; inx < fieldCnt; ++inx)
    118.  
    119. return retFont;
    120. }
    To copy to clipboard, switch view to plain text mode 

  8. The following user says thank you to philw for this useful post:

    d_stranz (16th September 2014)

  9. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,248
    Thanks
    304
    Thanked 867 Times in 854 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Setting font has no effect in QGraphicsItem subclass paint() method

    is there a general way to determine if a given QFont is a serif or sans-serif font?
    QFontInfo and QFontDatabase might be able to tell you some of that.

Similar Threads

  1. Paint selection in QStyledItemDelegate's subclass
    By woodtluk in forum Qt Programming
    Replies: 2
    Last Post: 26th April 2012, 16:51
  2. Use OpenGL in QGraphicsItem paint method
    By subsonic in forum Qt Programming
    Replies: 0
    Last Post: 27th November 2011, 15:54
  3. Replies: 3
    Last Post: 19th April 2011, 11:27
  4. Replies: 5
    Last Post: 5th September 2009, 07:34
  5. paint method
    By zgulser in forum Newbie
    Replies: 6
    Last Post: 20th July 2009, 09:57

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.