Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

character width in a string rendered by DrawText



  • I was trying to calculated the number of chars that I can put in a single row in a window. I got the font (I used Monaco, which is a fixed width font) width with QFontMetrics first, and then divide the window width by this font width. However, when I'm using the DrawText or QTextDocument to render text, I found the width of the rendered text does not equal to the number of chars * the font width.

    My question is why would this happen? Is there any way to control the exact width of a char in a DrawText or QTextDocument render?



  • @caojx
    I really would have thought a fixed width font should be doable as you say. Perhaps you'd better show your code, and just how the multiplication comes out compared to what DrawText is doing? Is there perhaps some kind of inter-character spacing?



  • Here's my code:

    from PyQt5 import QtGui
    from PyQt5.QtWidgets import QApplication, QMainWindow
    from PyQt5.QtGui import QPainter, QTextDocument
    from PyQt5.QtCore import QRect, Qt, QRectF
    from PyQt5.QtGui import QPainter, QFont, QFontMetrics
    import sys
    
    
    class Window(QMainWindow):
        def __init__(self):
            super().__init__()
            self.show()
    
            self.font = QFont('Monaco', 13)
            self.fm = QFontMetrics(self.font);
            self._font_width = self.fm.width(' ')
            self._font_height = self.fm.height()
    
        def paintEvent(self, event):
            painter = QPainter(self)
            painter.setFont(self.font)
            
            # Print with multi draw contents.
            for i in range(80):
                painter.drawText(
                    QRect(
                        i * self._font_width,
                        0,
                        (i + 1) * self._font_width,
                        self._font_height,
                    ),
                    Qt.AlignLeft,
                    'x',
                )
    
            # Print with a single draw contents.
            painter.drawText(
                QRect(
                    0,
                    self._font_height,
                    80 * self._font_width,
                    2 * self._font_height,
                ),
                Qt.AlignLeft,
                'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
            )
    
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec())
    

    This is what it looks like:

    8f9847df-74aa-451c-bd75-3729647ce2f6-image.png

    Apparent the whole string draw text render is wider than rendering them one by one.

    I'm pretty sure that I didn't do any spacing in between characters, I just used the font width. Maybe DrawText put some spacing in between them? I'm curious what are they.



  • @caojx
    You are working off QFontMetric::width(). What version of Qt are you? I'm thinking that https://kdepepo.wordpress.com/2019/08/05/about-deprecation-of-qfontmetricswidth/ holds the clue, which you should read. Stuff like:

    The graphics shown at https://doc.qt.io/qt-5/qfontmetrics-obsolete.html#width illustrates that there is a difference between the horizontal advance, i.e. the number of pixels from one character to the next character, and the bounding rectangle width, which is needed to encompass all pixels including so called bearings that can overlap the next or the previous character.

    ?



  • @JonB Thanks for the reply. My pyqt5 version is 5.14.1. I did also try to use horizontalAdvance, but it seems to generate the same result.


Log in to reply