【问题标题】:Qt - How to count and measure the lines in a QTextDocument?Qt - 如何计算和测量 QTextDocument 中的行数?
【发布时间】:2020-04-03 16:30:09
【问题描述】:

在我的一个项目中,我创建了一个 QTextDocument,它拥有我需要绘制的文本。该文本是一个自动换行的 HTML 格式文本,它应该绘制在一个矩形区域中,我知道该区域的宽度。它的内容也永远不会超过一个段落。

文本文档创建如下:

// create and configure the text document to measure
QTextDocument textDoc;
textDoc.setHtml(text);
textDoc.setDocumentMargin(m_TextMargin);
textDoc.setDefaultFont(m_Font);
textDoc.setDefaultTextOption(m_TextOption);
textDoc.setTextWidth(m_Background.GetMessageWidth(size().width()));

这是我要绘制的示例文本:

Ceci est un texte <img src=\"Resources/1f601.svg\" width=\"24\" height=\"24\"> avec <img src=\"Resources/1f970.svg\" width=\"24\" height=\"24\"> une <img src=\"Resources/1f914.svg\" width=\"24\" height=\"24\"> dizaine <img src=\"Resources/1f469-1f3fe.svg\" width=\"24\" height=\"24\"> de <img src=\"Resources/1f3a8.svg\" width=\"24\" height=\"24\"> mots. Pour voir comment la vue réagit.

图像是从 qml 资源中获取的 SVG 图像。

为了在绘制文本时执行多项操作,我需要知道在应用自动换行后将绘制多少行,以及自动换行文本中任何行的高度。

我尝试在文本文档提供的函数中搜索,以及QTextBLock、QTextFragment和QTextCursor中提供的函数。我尝试了几种方法,例如用光标遍历字符并计算行数,或计算块中的每个片段。不幸的是,它们都没有奏效:所有的函数总是算 1 行,或者只是失败。

这是我已经尝试过的一些代码示例,但没有成功:

// FAILS - always return 1
int lineCount = textDoc.lineCount()

// FAILS - always return 1
int lineCount = textDoc.blockCount()

// FAILS - return the whole text height, not a particular line height at index
int lineHeight = int(textDoc.documentLayout()->blockBoundingRect(textDoc.findBlockByNumber(lineNb)).height());
// get the paragraph (there is only 1 paragraph in the item text document
QTextBlock textBlock = textDoc.findBlockByLineNumber(lineNb);

int blockCount = 0;

for (QTextBlock::iterator it = textBlock.begin(); it != textBlock.end(); ++it)
{
    // FAILS - fragments aren't divided by line, e.g an image will generate a fragment
    QString blockText = it.fragment().text();
    ++blockCount;
}

return blockCount;
QTextCursor cursor(&textDoc);

int lineCount = 0;

cursor.movePosition(QTextCursor::Start);

// FAILS - movePosition() always return false
while (cursor.movePosition(QTextCursor::Down))
    ++lineCount;

我无法弄清楚我做错了什么,以及为什么我的所有方法都失败了。

所以我的问题是:

  1. 如何计算我的自动换行文档中包含的行数
  2. 如何测量我的自动换行文档中的行高
  3. 文本文档功能是否因为html格式而失败?如果是,在这种情况下我应该如何实现我的目标?

注意 我知道如何测量整个文本的高度。但是,由于每个行高可能不同,我不能只将整个文本高度除以行,所以这对我来说不是一个可接受的解决方案。

【问题讨论】:

    标签: qt count line measure qtextdocument


    【解决方案1】:

    我终于找到了解决问题的方法。文本文档不能直接用于测量单个行,布局应该用于此目的,如下文所述: https://forum.qt.io/topic/113275/how-to-count-and-measure-the-lines-in-a-qtextdocument

    所以下面的代码就是解决方案:

    //---------------------------------------------------------------------------
    int getLineCount(const QString& text) const
    {
        // create and configure the text document to measure
        QTextDocument textDoc;
        textDoc.setHtml(text);
        textDoc.setDocumentMargin(m_TextMargin);
        textDoc.setDefaultFont(m_Font);
        textDoc.setDefaultTextOption(m_TextOption);
        textDoc.setTextWidth(m_Background.GetMessageWidth(size().width()));
    
        // this line is required to force the document to create the layout, which will then be used
        //to count the lines
        textDoc.documentLayout();
    
        // the document should at least contain one block
        if (textDoc.blockCount() < 1)
            return -1;
    
        int lineCount = 0;
    
        // iterate through document paragraphs (NOTE normally the message item should contain only 1 paragraph
        for (QTextBlock it = textDoc.begin(); it != textDoc.end(); it = it.next())
        {
            // get the block layout
            QTextLayout* pBlockLayout = it.layout();
    
            // should always exist, otherwise error
            if (!pBlockLayout)
                return -1;
    
            // count the block lines
            lineCount += pBlockLayout->lineCount();
        }
    
        return lineCount;
    }
    //---------------------------------------------------------------------------
    int measureLineHeight(const QString& text, int lineNb, int blockNb) const
    {
        // create and configure the text document to measure
        QTextDocument textDoc;
        textDoc.setHtml(text);
        textDoc.setDocumentMargin(m_TextMargin);
        textDoc.setDefaultFont(m_Font);
        textDoc.setDefaultTextOption(m_TextOption);
        textDoc.setTextWidth(m_Background.GetMessageWidth(size().width()));
    
        // this line is required to force the document to create the layout, which will then be used
        //to count the lines
        textDoc.documentLayout();
    
        // check if block number is out of bounds
        if (blockNb >= textDoc.blockCount())
            return -1;
    
        // get text block and its layout
        QTextBlock   textBlock = textDoc.findBlockByNumber(blockNb);
        QTextLayout* pLayout   = textBlock.layout();
    
        if (!pLayout)
            return -1;
    
        // check if line number is out of bounds
        if (lineNb >= pLayout->lineCount())
            return -1;
    
        // get the line to measure
        QTextLine textLine = pLayout->lineAt(lineNb);
    
        return textLine.height();
    }
    //---------------------------------------------------------------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      相关资源
      最近更新 更多