2011-12-26 18 views
14

Ho una QLabel di larghezza fissa.
Ho bisogno di verificare (periodicamente) che l'intera stringa si adatti all'interno della QLabel alla sua larghezza attuale, così posso ridimensionarla in modo appropriato.Qt - Ottieni la lunghezza in pixel di una stringa in una QLabel

Per fare ciò, ho bisogno di ottenere la 'lunghezza pixel' della stringa.
(La quantità totale di pixel orizzontali richiesti per visualizzare la stringa).
Si noti che la dimensione in punti della QLabel non cambia mai.

Example of 'Pixel Width' of a string

Non posso semplicemente controllare la quantità di caratteri presenti, poiché alcuni caratteri sono pedice/apice e contribuisce in modo diverso alla larghezza della stringa completa.
(Ciò significa che non esiste una semplice relazione tra la larghezza del pixel e la quantità di caratteri)

Esiste una funzione di super convivenza astratta per questo?

Spec:
Python 2.7.1
PyQt4
Windows 7

risposta

22

Per ottenere la precisione pixel-larghezza del testo, è necessario utilizzare QFontMetrics.boundingRect.

Non utilizzare QFontMetrics.width, perché tiene conto della direzione sinistra e destra dei caratteri. Questo spesso (ma non sempre) porta a risultati che possono essere diversi pixel in più o in meno rispetto alla larghezza di pixel completa.

Quindi, per calcolare il pixel-larghezza del testo dell'etichetta, usare qualcosa come:

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

EDIT

Ci sono tre diversi QFontMetrics metodi che possono essere utilizzati per calcolare la "larghezza "di una stringa: size(), width() e boundingRect().

Tuttavia, anche se tutti danno risultati leggermente diversi, nessuno di essi sembra restituire costantemente l'esatta larghezza del pixel in tutte le circostanze. Quale è la migliore dipende in gran parte dalla famiglia di font corrente in uso e su quali caratteri particolari sono all'inizio e alla fine della stringa.

Ho aggiunto sotto uno script che testa i tre metodi. Per me, il metodo boundingRect dà i risultati più coerenti. Gli altri due metodi tendono ad essere leggermente troppo ampi, o ritagliano il secondo campione di testo quando viene usato un font serif (questo è con PyQt 4.9 e Qt 4.8 su 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_()) 
+0

Voglio che i cuscinetti siano considerati, ma grazie comunque! –

+0

@AntiEarth. I cuscinetti possono essere negativi, quindi se vengono presi in considerazione ai fini del ridimensionamento, il testo dell'etichetta può essere ritagliato ai bordi. Solo il 'boundingRect' garantisce sempre l'intera larghezza del pixel del testo. – ekhumoro

+0

Non ci tiene conto degli abbonamenti, vero? Solo la dimensione del punto? –

Problemi correlati