qt font-size autosize

Para Qt 4.6.x, ¿cómo se ajusta automáticamente el tamaño del texto para que se ajuste a un ancho específico?



font-size autosize (7)

Dentro de mi QGraphicsRectItem :: paint (), intento dibujar el nombre del elemento dentro de su rect (). Sin embargo, para cada uno de los diferentes elementos, pueden ser de ancho variable y, de manera similar, los nombres pueden ser de longitud variable.

Actualmente estoy comenzando con un tamaño de fuente máximo, verificando si se ajusta y disminuyo hasta que encuentre un tamaño de fuente que se ajuste. Hasta ahora, no he podido encontrar una manera rápida y fácil de hacer esto. ¿Hay una forma mejor o más eficiente de hacer esto?

¡Gracias!

void checkFontSize(QPainter *painter, const QString& name) { // check the font size - need a better algorithm... this could take awhile while (painter->fontMetrics().width(name) > rect().width()) { int newsize = painter->font().pointSize() - 1; painter->setFont(QFont(painter->font().family(), newsize)); } }


Aquí está mi código, el ajuste (en altura) de un texto, funciona bastante bien (error <2%, supongo)

void scalePainterFontSizeToFit(QPainter &painter, QFont &r_font, float _heightToFitIn) { float oldFontSize, newFontSize, oldHeight; // Init oldFontSize=r_font.pointSizeF(); // Loop for (int i=0 ; i<3 ; i++) { oldHeight = painter.fontMetrics().boundingRect(''D'').height(); newFontSize = (_heightToFitIn / oldHeight) * oldFontSize; r_font.setPointSizeF(newFontSize); painter.setFont(r_font); oldFontSize = newFontSize; //qDebug() << "OldFontSize=" << oldFontSize << "HtoFitIn=" << _heightToFitIn << " fontHeight=" << oldHeight << " newFontSize=" << newFontSize; } // End r_font.setPointSizeF(newFontSize); painter.setFont(r_font); }


Esto depende del rango en el que espera que varíen los tamaños de fuente. Si el rango es grande, el incremento de uno en uno puede llevar mucho tiempo. Si solo se trata de varios tamaños de puntos, la velocidad probablemente no será un problema.

Si el rango es grande, otro enfoque sería agregar un intervalo más grande, en lugar de ''1''. Si excede el tamaño deseado en un paso, reduzca el intervalo, por ejemplo, a la mitad. Rebotarás hacia adelante y hacia atrás a través del tamaño óptimo en cantidades cada vez más pequeñas; cuando la diferencia entre dos intervalos sucesivos es pequeña, puede salir.

Esto es similar al enfoque utilizado en la búsqueda de raíces. Puede ser excesivo, ya que es probable que el tamaño de las fuentes que sea aceptable para mostrar en una aplicación determinada sea bastante estrecho, y el enfoque de fuerza bruta que ya está usando no consumirá mucho tiempo.


Johannes de qtcentre.org ofreció la siguiente solución:

float factor = rect().width() / painter->fontMetrics().width(name); if ((factor < 1) || (factor > 1.25)) { QFont f = painter->font(); f.setPointSizeF(f.pointSizeF()*factor); painter->setFont(f); }

Lo intenté en mi programa y hasta ahora, parece funcionar bastante bien. Me gusta porque produce resultados en una sola pasada, pero asume que la anchura de la fuente es igual a su altura.

http://www.qtcentre.org/threads/27839-For-Qt-4-6-x-how-to-auto-size-text-to-fit-in-a-specified-width


Lamentablemente no. No hay una solución fácil para esto. La mejora más obvia, en cuanto al rendimiento, sería calcular y almacenar en caché el tamaño de fuente necesario cuando se cambia el texto en lugar de recalcularlo en cada evento de pintura. Otra mejora sería tratar de estimar el tamaño correcto en función de las proporciones del límite delimitado. Hacer y probar estimaciones debería hacer que corrijas el tamaño mucho más rápido que simplemente disminuyendo el tamaño del punto en una iteración.


Podría tener un QGraphicsTextItem como un elemento secundario del elemento rect, medir el ancho del elemento de texto y luego escalar el elemento de texto (setTransform ()) para que se ajuste al ancho (y la altura) del elemento rect.


Divide una conquista

Podría reducir el número de pases en su método de fuerza bruta: digamos que su tamaño de fuente preferido (máximo) es 40 y tiene un tamaño de fuente mínimo de 0

if (40 == false && 0 == true)

  • 20 = verdadero // divide las posibilidades a la mitad con cada conjetura
  • 30 = falso
  • 25 = verdadero
  • 27 = verdadero
  • 28 = falso
  • entonces 27 victorias

¿De qué manera es esto mejor?

esto tomó 6 conjeturas en lugar de 13, e incluso si 20, 12 o 39 fueran la respuesta correcta, siempre se necesitarían aproximadamente 6 conjeturas. por lo tanto, no solo es menos conjeturas la mayor parte del tiempo, sino que es más consistente, lo que es importante para la experiencia del usuario.

Creo que la cantidad de conjeturas que se toman al dividir las partes por la mitad cada vez es la raíz cuadrada del rango que estás buscando más uno. Math.sqroot (40-0) + 1 (Eso es solo una conjetura, siéntase libre de corregirme). Su tamaño de fuente mínimo probablemente no sea 0, por lo que aumentar esto aceleraría la búsqueda de una respuesta.

Ilustración:

Es como jugar a Guess Who, los jugadores que preguntan "¿tu nombre tiene una A" y reducen las posibilidades a la mitad? Sin importar lo que contestes, la respuesta suele ser más rápida que la del jugador que pregunta 1 personaje por turno "es tu nombre Sam" " es tu nombre alex "

Alternativa: comenzar con una buena suposición, luego probar la precisión También promovería trabajar con cierta lógica para usar el resultado provisto por la respuesta de Daren usando fontMetrics como una buena estimación inicial y luego probarlo, si se ajusta a la prueba +2 si no es así. t prueba de ajuste -2; si la nueva prueba se ajusta, prueba el 1 que omitiste y sabrás tu respuesta, si no intentas mover otro 2 y así sucesivamente, pero lo ideal es que la respuesta de FontMetrics no esté a más de 4 ...

Sospecho que esto producirá los resultados promedio más rápidos de los casos de uso reales.

Suponiendo que desee un int y suponiendo que las inexactitudes de las métricas de la fuente son mínimas, probablemente solo se tomarán 2 o 3 intentos.


void myClass::adaptFontSize(QPainter * painter, int flags, QRectF drawRect, QString text){ int flags = Qt::TextDontClip|Qt::TextWordWrap; //more flags if needed QRect fontBoundRect = painter->fontMetrics().boundingRect(drawRect.toRect(),flags, text); float xFactor = drawRect.width() / fontBoundRect.width(); float yFactor = drawRect.height() / fontBoundRect.height(); float factor = xFactor < yFactor ? xFactor : yFactor; QFont f = painter->font(); f.setPointSizeF(f.pointSizeF()*factor); painter->setFont(f); }

O más preciso pero codicioso.

void myClass::adaptFontSize(QPainter * painter, int flags, QRectF rect, QString text, QFont font){ QRect fontBoundRect; fontBoundRect = painter->fontMetrics().boundingRect(rect.toRect(),flags, text); while(rect.width() < fontBoundRect.width() || rect.height() < fontBoundRect.height()){ font.setPointSizeF(font.pointSizeF()*0.95); painter->setFont(font); fontBoundRect = painter->fontMetrics().boundingRect(rect.toRect(),flags, text); } }