Подтвердить что ты не робот

Qt - получить длину пикселя строки в QLabel

У меня есть QLabel фиксированной ширины.
Мне нужно проверить (периодически), что вся строка помещается внутри QLabel с текущей шириной, поэтому я могу изменить ее размер соответствующим образом.

Чтобы сделать это, мне нужно получить "длину пикселя" строки.
(Общее количество горизонтальных пикселей, необходимых для отображения строки).
Следует отметить, что размер точки QLabel никогда не изменяется.

Example of 'Pixel Width' of a string

Я не могу просто проверить количество присутствующих символов, так как некоторые символы являются индексом/надстрочным индексом и вносят по-разному в ширину всю строку.
(Это означает, что нет простой взаимосвязи между шириной пикселя и количеством символов)

Есть ли какая-либо абстрактная, супер-удобная функция для этого?

Технические характеристики:
Python 2.7.1
PyQt4
Windows 7

4b9b3361

Ответ 1

Чтобы получить точную ширину пикселя текста, вы должны использовать QFontMetrics.boundingRect.

Не используйте QFontMetrics.width, так как он учитывает левый и правый подшипники символов. Это часто (но не всегда) приводит к результатам, которые могут быть в несколько пикселей больше или меньше, чем полная ширина пикселя.

Итак, чтобы вычислить ширину пикселя текста метки, используйте что-то вроде:

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

ИЗМЕНИТЬ

Существуют три разных метода QFontMetrics, которые можно использовать для вычисления "ширины" строки: size(), width() и boundingRect().

Однако, хотя все они дают несколько разные результаты, ни один из них, похоже, не всегда возвращает точную ширину пикселя при любых обстоятельствах. Какой из них лучше всего зависит в основном от текущего используемого семейства шрифтов и от того, какие конкретные символы находятся в начале и конце строки.

Я добавил ниже script, который проверяет три метода. Для меня метод boundingRect дает наиболее последовательные результаты. Другие два метода имеют тенденцию быть либо слишком широкими, либо зажимать второй образец текста при использовании шрифта с засечками (это с PyQt 4.9 и Qt 4.8 в 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_())