Qt - 如何获取 QLabel 中字符串的像素长度?

发布于 2024-12-23 05:47:22 字数 383 浏览 4 评论 0原文

我有一个固定宽度的 QLabel。
我需要(定期)检查整个字符串是否适合 QLabel 的当前宽度,以便我可以适当地调整它的大小。

为此,我需要获取字符串的“像素长度”。
(显示字符串所需的水平像素总数)。
应该注意的是,QLabel 的点大小永远不会改变。

字符串的“像素宽度”示例

我无法简单地检查存在的字符数量,因为某些字符是下标 /上标并对整个字符串的宽度贡献不同。
(这就是说像素宽度和字符数量之间没有简单的关系)

是否有任何抽象的、超级方便的函数?

规格:
Python 2.7.1
PyQt4
视窗7

I have a QLabel of a fixed width.
I need to check (periodically) that the entire string fits inside the QLabel at its current width, so I can resize it appropriately.

To do this, I need to obtain the 'pixel length' of the string.
(The total amount of horizontal pixels required to display the string).
It should be noted that the point size of the QLabel never changes.

Example of 'Pixel Width' of a string

I can not simply check the amount of characters present, since some characters are subscript / superscript and contribute differently to the width of the entire string.
(This is to say there is no simple relationship between pixel width and the amount of characters)

Is there any abstracted, super conveniant function for this?

Specs:
Python 2.7.1
PyQt4
Windows 7

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

相守太难 2024-12-30 05:47:23

要获取文本的精确像素宽度,您必须使用 QFontMetrics.boundingRect

不要使用 QFontMetrics.width,因为它考虑了左和右字符的正确方位。这通常(但并非总是)导致结果可能比整个像素宽度多或少几个像素。

因此,要计算标签文本的像素宽度,请使用以下内容:

width = label.fontMetrics().boundingRect(label.text()).width()

EDIT

有三种不同的 QFontMetrics 方法可用于计算标签文本的“宽度”字符串:size()width()boundingRect()

然而,尽管它们给出的结果略有不同,但似乎没有一个在所有情况下都能一致地返回精确的像素宽度。哪一种最好主要取决于当前使用的字体系列以及字符串开头和结尾的特定字符。

我在下面添加了一个测试这三种方法的脚本。对我来说,boundingRect 方法给出了最一致的结果。其他两种方法往往要么稍微太宽,要么在使用衬线字体时剪切第二个文本样本(这是 Linux 上的 PyQt 4.9 和 Qt 4.8)。

from PyQt4 import QtGui, QtCore

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setAutoFillBackground(True)
        self.setBackgroundRole(QtGui.QPalette.Mid)
        self.setLayout(QtGui.QFormLayout(self))
        self.fonts = QtGui.QFontComboBox(self)
        self.fonts.currentFontChanged.connect(self.handleFontChanged)
        self.layout().addRow('font:', self.fonts)
        for text in (
            u'H\u2082SO\u2084 + Be',
            u'jib leaf jib leaf',
            ):
            for label in ('boundingRect', 'width', 'size'):
                field = QtGui.QLabel(text, self)
                field.setStyleSheet('background-color: yellow')
                field.setAlignment(QtCore.Qt.AlignCenter)
                self.layout().addRow(label, field)
        self.handleFontChanged(self.font())

    def handleFontChanged(self, font):
        layout = self.layout()
        font.setPointSize(20)
        metrics = QtGui.QFontMetrics(font)
        for index in range(1, layout.rowCount()):
            field = layout.itemAt(index, QtGui.QFormLayout.FieldRole).widget()
            label = layout.itemAt(index, QtGui.QFormLayout.LabelRole).widget()
            method = label.text().split(' ')[0]
            text = field.text()
            if method == 'width':
                width = metrics.width(text)
            elif method == 'size':
                width = metrics.size(field.alignment(), text).width()
            else:
                width = metrics.boundingRect(text).width()
            field.setFixedWidth(width)
            field.setFont(font)
            label.setText('%s (%d):' % (method, width))

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

To get the precise pixel-width of the text, you must use QFontMetrics.boundingRect.

Do not use QFontMetrics.width, because it takes into account the left and right bearing of the characters. This will often (but not always) lead to results which can be several pixels more or less than the full pixel-width.

So, to calculate the pixel-width of the label text, use something like:

width = label.fontMetrics().boundingRect(label.text()).width()

EDIT

There are three different QFontMetrics methods which can be used to calculate the "width" of a string: size(), width() and boundingRect().

However, although they all give slightly different results, none of them seems to consistently return the exact pixel-width in all circumstances. Which one is best depends mostly on the current font-family in use and on which particular characters are at the beginning and end of the string.

I have added below a script that tests the three methods. For me, the boundingRect method gives the most consistent results. The other two methods tend to be either slightly too wide, or clip the second text sample when a serif font is used (this is with PyQt 4.9 and Qt 4.8 on Linux).

from PyQt4 import QtGui, QtCore

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setAutoFillBackground(True)
        self.setBackgroundRole(QtGui.QPalette.Mid)
        self.setLayout(QtGui.QFormLayout(self))
        self.fonts = QtGui.QFontComboBox(self)
        self.fonts.currentFontChanged.connect(self.handleFontChanged)
        self.layout().addRow('font:', self.fonts)
        for text in (
            u'H\u2082SO\u2084 + Be',
            u'jib leaf jib leaf',
            ):
            for label in ('boundingRect', 'width', 'size'):
                field = QtGui.QLabel(text, self)
                field.setStyleSheet('background-color: yellow')
                field.setAlignment(QtCore.Qt.AlignCenter)
                self.layout().addRow(label, field)
        self.handleFontChanged(self.font())

    def handleFontChanged(self, font):
        layout = self.layout()
        font.setPointSize(20)
        metrics = QtGui.QFontMetrics(font)
        for index in range(1, layout.rowCount()):
            field = layout.itemAt(index, QtGui.QFormLayout.FieldRole).widget()
            label = layout.itemAt(index, QtGui.QFormLayout.LabelRole).widget()
            method = label.text().split(' ')[0]
            text = field.text()
            if method == 'width':
                width = metrics.width(text)
            elif method == 'size':
                width = metrics.size(field.alignment(), text).width()
            else:
                width = metrics.boundingRect(text).width()
            field.setFixedWidth(width)
            field.setFont(font)
            label.setText('%s (%d):' % (method, width))

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文