19

固定幅の QLabel があります。
文字列全体が現在の幅で QLabel 内に収まることを (定期的に) チェックする必要があるため、適切にサイズを変更できます。

これを行うには、文字列の「ピクセル長」を取得する必要があります。
(文字列を表示するために必要な水平ピクセルの合計量)。
QLabel のポイント サイズは変更されないことに注意してください。

文字列の「ピクセル幅」の例

一部の文字は下付き/上付きで、文字列全体の幅に異なる影響を与えるため、存在する文字の量を単純に確認することはできません。
(つまり、ピクセル幅と文字数の間には単純な関係はありません)

これには、抽象化された非常に便利な機能がありますか?

仕様:
Python 2.7.1
PyQt4
Windows 7

4

1 に答える 1

30

テキストの正確なピクセル幅を取得するには、QFontMetrics.boundingRectを使用する必要があります。

文字の左右の向きが考慮されるため、QFontMetrics.widthは使用しないでください。これにより、多くの場合 (常にではありません)、全ピクセル幅より数ピクセル多いまたは少ない結果が得られます。

したがって、ラベル テキストのピクセル幅を計算するには、次のようなものを使用します。

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

編集

QFontMetrics文字列の「幅」を計算するために使用できる3 つの異なる方法があります: size()width()およびboundingRect()

ただし、すべてわずかに異なる結果が得られますが、すべての状況で一貫して正確なピクセル幅を返すものはないようです。どちらが最適かは、現在使用されているフォント ファミリと、文字列の先頭と末尾にある特定の文字に大きく依存します。

3 つの方法をテストするスクリプトを以下に追加しました。私にとっては、このboundingRect方法が最も一貫した結果をもたらします。他の 2 つの方法は、やや幅が広すぎるか、セリフ フォントが使用されている場合に 2 番目のテキスト サンプルが切り取られる傾向があります (これは、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_())
于 2011-12-26T18:17:31.563 に答える