QT QFontMetrics boundingRect failed to textwordwrap



  • 你好,在QT4.8中有如下代码,想计算换行后矩形的尺寸,结果返回的矩形尺寸显示并没有换行,是按照单行来计算的。

    QPainter painter(this);
    QString text("1234567890123456789012345678901234567890"
                 "1234567890123456789012345678901234567890"
                 "1234567890123456789012345678901234567890"
                 "1234567890123456789012345678901234567890");
    int width = this->width()-40;
    int flags = Qt::TextWordWrap;
    qDebug()<<"font:"<<painter.font().pointSize()<<",pixelSize="<<painter.font().pixelSize();
    QFontMetrics metrics = painter.fontMetrics();
    QRect textBoundingRect = metrics.boundingRect(QRect(0,0,width,0),flags,text);
    painter.translate(20,20);
    painter.drawRect(textBoundingRect);
    painter.drawText(textBoundingRect,Qt::TextWordWrap,text);


  • @vitasr 您好!

    其实你的text并没有换行。你只是在代码中进行了视觉上的换行。text里面的内容依然是一行。

    我也测试了一些,直接QDebug并没有换行的效果;

        QString text;
        text.append("1234");
        text.append(QChar('\n\r'));
        text.append("1234");
        qDebug() << text; ///不换行
    
        char *p = "12345\n1234";
        qDebug("%s",p);// 换行
    
        QString str(p);
        qDebug() << str; //不换行
    

    帮助文档中,已经有了对应的解释:

    QRect QFontMetrics::boundingRect(const QString &text) const
    Returns the bounding rectangle of the characters in the string specified by text. The bounding rectangle always covers at least the set of pixels the text would cover if drawn at (0, 0).
    Note that the bounding rectangle may extend to the left of (0, 0), e.g. for italicized fonts, and that the width of the returned rectangle might be different than what the width() method returns.
    If you want to know the advance width of the string (to lay out a set of strings next to each other), use width() instead.
    Newline characters are processed as normal characters, not as linebreaks.
    The height of the bounding rectangle is at least as large as the value returned by height().

    希望对您有所帮助。



  • 感谢你的回复,字符串我只是故意写成那样,我知道这样其实并不代表换行了。但是我的理解是 我要计算一个较长的字符串QString所占用的矩形尺寸,而且我在参数中已经设置了 Qt::TextWordWrap属性,那么计算出来的矩形不应该是换行以后的矩形尺寸吗?否则 我计算矩形时传递这个参数还有什么意义呢?我难道必须要自己将字符串拆分成多个字符串再计算所有矩形的尺寸吗?boundingRect的真实含义不应该是自动计算换行后的矩形吗?



  • @vitasr PS:回复的时候,可以@我 一下,这样我上线的话,会有一个明显的提示。

    1. Qt::TextWordWrap 在这里不是自动换行。 如果你的字符串里面有\n的,这个参数,可以在boundingRect中计算多行。前提是字符串中有\n. 同时另外一个参数Qt::TextSingleLine,可以忽略字符串中的换行的。(可能理解的误区在这里。)
    2. boundingRect的真实含义不应该是自动计算换行后的矩形? 它是计算了换行后的矩形,前提是你的内容必须有换行,然后加上TextWordWrap.参数即可。


  • @joeQ ,非常感谢!我现在遇到的问题是 我拿到了一个很长的字符串,但是这个字符串中间没有换行符,而且字符串内容可能有中文,我必须要在界面上把这个字符串给完整的绘制出来(必须多行才能显示完,使用drawText),因此,我必须要能够有一种方法把这个字符串拆分成多行,再使用drawText绘制出来,请问有什么方法能够实现这个功能吗?



  • @vitasr 你的问题,让我想到了微信“15个。”引起的一个问题。 微信在处理文字排版的时候,也是通过一个一个计算来进行排版的。

    QRect boundingRect(QChar ch) const
    QRect boundingRect(const QString &text) const
    QRect boundingRect(const QRect &rect, int flags, const QString &text, int tabStops = 0, int *tabArray = Q_NULLPTR) const
    QRect boundingRect(int x, int y, int width, int height, int flags, const QString &text, int tabStops = 0, int *tabArray = Q_NULLPTR) const

    我们知道boundingRect有多个重载函数。其实最终都是调用的第一个处理的。根据你的问题,给出一下解决建议:

    1. QChar本身已经支持中文了,所以不用考虑字节问题了;
    2. 文字在界面上显示的区域,我们是知道的。记作:uiRect
    3. 当我们在某个字号下,我们可以依次遍历字符串中的每个QChar,计算它的chRect. 每计算一个新的,就和前面的united合并,然后判断 宽高是否超出uiRect. 如果宽超出的话,那就换行。如果高超出的话,你可以做其他处理...

    或者

    1. 每计算一个字符,绘制一个字符。

    看似麻烦一些,每一步都是简单的,代码量不会太多的,都是在循环中,计算量也不会很大。有多长? QString最大可以存多长呢?



  • @joeQ ,好的,非常感谢!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.