2010-02-04 73 views
14

在我的QGraphicsRectItem :: paint()中,我试图在它的rect()中绘制该项目的名称。但是,对于每个不同的项目,它们可以具有可变的宽度,并且类似的名称可以具有可变的长度。对于Qt 4.6.x,如何自动调整文本大小以适应指定的宽度?

目前我以最大字体大小开始,检查它是否适合并递减,直到找到适合的字体大小为止。到目前为止,我还没有找到一个快速简单的方法来做到这一点。有没有更好或更有效的方法来做到这一点?

谢谢!

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)); 
} 
} 
+0

参见[这个问题](http://stackoverflow.com/q /1329652分之36575192)。 – 2016-11-29 14:28:53

回答

14

约翰内斯提供了以下解决方案:

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); 
} 

我给它一个尝试在我的计划,到目前为止,似乎工作得很好。我喜欢它,因为它一次就会产生结果,但它假定字体宽度与其高度一样。

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

+1

为什么是1.25? 10个字符 – marmistrz 2013-08-27 14:02:35

+1

我试过这个,发现它是不准确的,至少对于一些字体。 OP的方法是准确的,但它是一种强力。 – Isaac 2015-05-29 11:48:42

+0

整数除法,(浮点)类型转换丢失。否则,如果小于1,则因子将为0. – ragnarius 2017-06-29 10:40:49

0

不幸的是,没有。对此没有简单的解决方案。最明显的改进是性能明智的计算,并且在文本改变时缓存所需的字体大小,而不是在每个paintEvent中重新计算它。另一个改进是尝试根据边界矩的比例来估计正确的大小。制作和测试评估应该让您更准确地调整大小,而不仅仅是每次迭代减少一次点大小。从qtcentre.org

2

你可以有一个QGraphicsTextItem作为RECT项目的孩子,测量文本项目的宽度,然后缩放文本项目(一个setTransform())以适合RECT项目的宽度(和高度)。

0

这取决于您期望字体大小变化的范围。如果范围很大,则递增1可能需要很长时间。如果只是几个点数的问题,速度可能不会成为问题。

如果范围很大,另一种方法是添加较大的区间,而不是“1”。如果您在一个步骤中超出了所需的尺寸,请将间隔减少一半。你会在每次越来越小的数量上来回穿越最佳尺寸;当两个连续间隔之间的差异很小时,您可以退出。

这与根发现中使用的方法类似。这可能是矫枉过正的,因为在给定的应用程序中可以接受的字体大小可能相当狭窄,而且您已经使用的暴力方法不会浪费太多时间。

1
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); 

} 

或更准确,但贪婪

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); 
    } 
} 
1

鸿沟的征服:

你可以减少你的蛮力方法的遍数: 让我们说你的首选(最大值)字体大小是40,你有0

如果(40 ==假最小字体大小& 0 == TRUE)

  • 20 =真//划分可能性在一半与每个猜
  • 30 =假
  • 25 =真
  • 27 =真
  • 28 =假
  • 所以27胜

在哪些方面改进?

这花了6次猜测而不是13次,即使20,12或39是正确的答案,它总是需要大约6次猜测。所以不仅在大多数时候更少的猜测,而且对于用户体验来说更加一致。

我觉得除以整数一半每次当它需要猜测的数量范围的平方根您正在寻找在加一。 Math.sqroot(40-0)+ 1(这只是一个猜测,随时纠正我。) 您的最小字体大小可能不是0,所以增加这将加快搜索答案。

插图:

这就像玩猜猜我是谁,球员谁问:“你的名字有一个A”,并削减了一半的可能性不管你通常怎么回答找到了答案不是谁询问玩家更快约1个字符每回合“你的名字是山姆”,“你的名字是亚历克斯”

备选:开始有很好的猜测,然后准确性 我也将促进一些逻辑工作使用所提供的结果测试达仁的答案使用fontMetrics作为一个很好的开始猜测然后te如果它适合测试+2,如果它不适合测试-2;如果新测试符合测试你跳过1,你会知道你的答案,如果不尝试移动另一个2等,但理想情况下fontMetrics答案是不超过4远...

我怀疑这个将产生实际使用案例的最快平均结果。

假设你想要一个int和假定字体规格不准确之处是最小的,这将可能只需要2周或3的猜测。

+0

[牛顿的方法](https://en.wikipedia.org/wiki/Newton%27s_method)是一种类似的方法,并不是人为地限制它的速度收敛。二进制除法决定了每次迭代只有一个结果位。假设字体大小关系单调递增,牛顿的字典大小通常比字体大小这样的简单问题快得多,就像字体大小的浮点字体一样。 – 2016-11-29 14:34:13

1

这里是我的代码配合(在heigth)一文中,工作得非常好(误差< 2%我猜)

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); 
} 
相关问题