Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. drawing text with monospace font not giving the same bounding rect (Qt 5.13.2)

drawing text with monospace font not giving the same bounding rect (Qt 5.13.2)

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 2 Posters 967 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    lano1106
    wrote on last edited by lano1106
    #1

    It is getting late. I'm giving up for tonight. There is something that I don't understand. I was expecting exact same bounding rect for text strings having the same number of characters with a monospace font.

    I have tried 3 different fonts:

    • Source Code Pro
    • Courier New
    • DejaVu Sans Mono

    In LibreOffice, I get the expected result but somehow with Qt it doesn't. I have nailed down the problem to:

    QString("%1").arg(val, 5, 'f', 2);
    

    '10.99' and ' 8.88' will have different length. (what might be an important detail in the mystery is that this number is appended to a string ending with a space. Therefore, there can be 1 or 2 adjacent consecutive spaces. I suspect that some space used by the 2 spaces is 'optimized' out somewhere by something but this is all I can tell or guess...)

    My code looks like this (disregard the various font settings. I have been shooting in the dark but none of them is changing the result:

    LinkedChart::LinkedChart(const QString &name, QGraphicsItem *parent, Qt::WindowFlags wFlags)
    : QChart(parent, wFlags),
      m_name(name),
      m_textFont("Source Code Pro", 8),
      m_textItem(NULL)
    {
        m_textFont.setWeight(QFont::ExtraLight);
        m_textFont.setFixedPitch(true);
        m_textFont.setKerning(false);
        QFontInfo info(m_textFont);
        qDebug("family " + info.family().toLatin1() + " px: %d", info.pixelSize());
    }
    void StupidSimpleText::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        Q_UNUSED(widget);
    
        painter->setFont(font());
        painter->setPen(pen());
        QFontMetrics metrics(font());
        QString txt = text();
        QSize textSize  = metrics.size(Qt::TextSingleLine, txt);
        QRectF boundingRect;
        painter->drawText(QRectF(QPointF(0,0), textSize), Qt::AlignLeft|Qt::AlignVCenter, txt, &boundingRect);
        if (txt.startsWith("Ask Cm Vol:")) {
            qDebug() << txt.size() << boundingRect;
        }
    }
    

    The output is:

    family Source Code Pro px: 11
    77 QRectF(0,0 526x17)
    77 QRectF(0,0 526x17)
    77 QRectF(0,0 530x17)
    77 QRectF(0,0 526x17)
    77 QRectF(0,0 526x17)
    77 QRectF(0,0 530x17)
    77 QRectF(0,0 526x17)
    

    Is there some setting or secret text drawing knowledge that I am not aware of that would ensure that the bounding rect is always the same dimension for any strings of equal size?

    thank you very much!

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      I would check textSize instead boundingRect since the boudingRect is the real width needed afaiu.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      1
      • L Offline
        L Offline
        lano1106
        wrote on last edited by lano1106
        #3

        Ok good point. I would expect those 2 values to be equivalent (especially for monospace fonts...).

        I did add textSize to my qDebug statement, in my case, they seem to be the same:

        qDebug() << txt.size() << boundingRect << textSize;
        
        family Source Code Pro px: 11
        77 QRectF(0,0 530x17) QSize(530, 17)
        77 QRectF(0,0 530x17) QSize(530, 17)
        77 QRectF(0,0 530x17) QSize(530, 17)
        77 QRectF(0,0 530x17) QSize(530, 17)
        77 QRectF(0,0 518x17) QSize(518, 17)
        77 QRectF(0,0 530x17) QSize(530, 17)
        77 QRectF(0,0 530x17) QSize(530, 17)
        77 QRectF(0,0 526x17) QSize(526, 17)
        
        

        Ok, I guess it is time to read some good QPainter::drawText() code... I tried to avoid this but it seems to be the only way to figure out....

        Update: There is no way that I'm going to hunt this bug down inside Qt guts. I did put my nose into QTextEngine code and this beast is monstrously complex...

        I did play with:

        QString("%1").arg(val, 5, 'f', 2);
        

        by changing the fill character.... I don't understand anymore what monospace mean. This is the root of my problem. If I pick 'a', 'A' or '.' (dot) as the fill character, the issue is still present... BUT if I choose '0' (zero). The boundingRect becomes rock solid and stable for all my strings.

        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Monospace means that every character has the same width and height - for example 8x14 pixels. This means no other character will be drawn inside this rect. It does not mean that all character will fill the 8x14 pixel - some will only fill e.g. 2x13 (e.g. an 'i'), some maybe 8x12 (e.g. 'w') - and this is why you get back different widths for the bounding rect.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          2
          • L Offline
            L Offline
            lano1106
            wrote on last edited by lano1106
            #5

            Christian, I would agree if the bouding rect width difference was due to only the trailing character and I wouldn't care.

            This is a string that is updated based on mouse cursor position and the width difference occurs almost at the beginning of the string. This makes monitoring it almost as sickening as being rocked while in a boat during a big storm...

            Beside, I don't get it. If I take any text editor, open any file from a terminal with vi or emacs. The 79th character will always be aligned with all the other lines's 79th character no matter what is the text content. I can even achieve this with LibreOffice Writer when I use a monospace font.

            Why can't I with Qt? Why would it be different?

            1 Reply Last reply
            1
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @lano1106 said in drawing text with monospace font not giving the same bounding rect (Qt 5.13.2):

              The 79th character will always be aligned with all the other lines's 79th character no matter what is the text content

              This is also true for Qt - otherwise you qtcreator would not work. I would guess QPainter::drawText() is given a wrong rectangle and therefore it's jumping. I would use the QPointF version. Also please provide a minimal compilable example so we can debug your problem.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              1 Reply Last reply
              3
              • L Offline
                L Offline
                lano1106
                wrote on last edited by
                #7

                Christian,

                thanks a lot for your support. I'm trying to nail down the issue. Right now, I have a small program and this one gives me the correct behavior. I will build up from there until I'm able to reproduce the issue.

                monospace.h:

                #include <QWidget>
                
                class MonospaceIssue : public QWidget
                {
                    Q_OBJECT
                public:
                    MonospaceIssue(QWidget *parent = NULL);
                    virtual ~MonospaceIssue();
                protected:
                    virtual void paintEvent(QPaintEvent *event);
                };
                

                main.cpp:

                #include <QApplication>
                #include <QPainter>
                #include "monospace.h"
                
                MonospaceIssue::MonospaceIssue(QWidget *parent)
                : QWidget(parent)
                {
                }
                
                MonospaceIssue::~MonospaceIssue()
                {
                }
                
                void MonospaceIssue::paintEvent(QPaintEvent *event)
                {
                    QPainter painter(this);
                    QFont monoFont("Source Code Pro", 8);
                    painter.setFont(monoFont);
                    QPen magentaPen = QPen(QColor(Qt::magenta), 1);
                    painter.setPen(magentaPen);
                    QString shouldHaveSameWidthTxt =
                "WWWWWWWWWWW 27.87aaaaa 10.88Ecmd\n"
                "iiiiiiiiiii  7,14MMMMM  7.66Ecmd";
                    QFontMetrics metrics(monoFont);
                    QSize textSize  = metrics.size(0, shouldHaveSameWidthTxt);
                    QRectF boundingRect;
                    painter.drawText(QRectF(QPointF(0,0), textSize),
                                     Qt::AlignLeft|Qt::AlignVCenter, shouldHaveSameWidthTxt, &boundingRect);
                }
                
                int main(int argc, char *argv[])
                {
                    QApplication app(argc, argv);
                    MonospaceIssue MyWindow;
                    MyWindow.show();
                    return app.exec();
                }
                

                stay tuned.

                1 Reply Last reply
                2
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Maybe add a variable string for your painting by e.g enable mouse tracking and print out the mouse positions.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  0
                  • L Offline
                    L Offline
                    lano1106
                    wrote on last edited by lano1106
                    #9

                    Not necessary. I did just plug in the crafted string literal into my application. This is obviously not monospace that I am getting.

                    I will simplify things until I isolate the issue.

                    Simple test program output:
                    Simple test program output

                    Application output:
                    Application output

                    Almost there...

                    1 Reply Last reply
                    0
                    • L Offline
                      L Offline
                      lano1106
                      wrote on last edited by
                      #10

                      Ok. I am ashamed.... When I get stupid problems like this one... It means that I start to be tired and should look at it back the next morning... I have found my problem. The problem is all good. There was a crucial missing line in my code:

                      void LinkedChart::setInfoText(const QString &text)
                      {
                          if (text == m_text)
                              return;
                          m_text = text;
                          if (!m_textItem) {
                              if (!text.size()) return;
                      //        m_textItem = scene()->addSimpleText(text, m_textFont);
                              m_textItem = new StupidSimpleText(text);
                              scene()->addItem(m_textItem);
                              QPen magentaPen = QPen(QColor(Qt::magenta), 1);
                              m_textItem->setPen(magentaPen);
                      
                              m_textItem->setFont(m_textFont); // <<<----- I omitted to set my super duper monospace font in the Graphics Item
                      
                              QPointF plotTopLeft = plotArea().topLeft();
                              plotTopLeft.rx() += 5.0;
                              plotTopLeft.ry() += 5.0;
                              m_textItem->setPos(plotTopLeft);
                              
                              /*
                               * Connection to reposition the graphics item when/if the plotarea is changing.
                               */
                              connect(this, SIGNAL(plotAreaChanged(const QRectF &)),
                                      this, SLOT(ourPlotAreaChanged(const QRectF &)));
                          }
                          m_textItem->setText(text);
                      }
                      
                      1 Reply Last reply
                      3
                      • Christian EhrlicherC Offline
                        Christian EhrlicherC Offline
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Nice to see the problem solved :)

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved