QTextLayout手动换行

问题描述 投票:0回答:5

我正在尝试使用

QTextLayout
逐条渲染线条。我尝试将
wrapMode
设置为
QTextOption::ManualWrap
并为每一行调用
QTextLine::setNumColumns
,但整个文本显示在一行中。

我还尝试将

wrapMode
设置为
QTextOption::WrapAnywhere
,这次文本被分成行,但空行(仅由
\n
组成的行)不可见。

我尝试链接

Qt4
Qt5
,但没有结果。

我做错了什么?

c++ qt4 qt5
5个回答
0
投票

QTextLine 用于单行文本。如果您想要多行,请使用QTextEdit


0
投票

事实证明,

Qt
通过为每行创建一个新的
QTextLayout
来实现这一点。详情可以在
QPlainTextEdit::paintEvent(QPaintEvent *)
来源找到。


0
投票

您可以使用

QTextLine::setNumColumns()
来指定当前行适合的字符数,直到它中断。如果您知道文本行的长度,则可以在您想要的位置准确地断开每行。换行符似乎被
QTextLayout
忽略。

QTextOption opt;
opt.setWrapMode(QTextOption::WrapAnywhere);

QStringList text;
text.append("First line");
text.append("Another line");

layout.setText(text.join(""));
layout.beginLayout();

qreal h = 0;
for(const auto& line : text)
{
   QTextLine l = layout.createLine();
   if(!l.isValid()
      break;
   l.setNumColumns(line.length());
   l.setPosition(QPointF(0, h);
   h += l.height();
}

layout.endLayout();

其中

layout
QTextLayout
,您可以将其定义为小部件类或其他类中的成员。但请注意(至少在 Qt 4.8.x 中)如果您使用选项卡,这可能无法按预期工作。我尝试创建一个具有右侧和左侧制表位的布局(可以通过
QTextOption
QTextOption::Tab
配置),但我不知道如何让它正确设置换行符。计算以像素为单位的线宽也不容易,因为
QFontMetrics::size()
不支持除左对齐以外的制表位。


0
投票

QTextLine
作者:
QTextLayout.createLine();

QTextLayout
可以绘制一个
QTextBlock
ENTER字符或键是创建新的QTextBlock。因此,您必须为每个块绘制布局。

QTextBlock 不包含

"\n"
字符,因为该字符将文本拆分为新的
QTextBlock

我使用这个例子:

class KonuIcerik : public QGraphicsTextItem
{
public:
    QRectF boundingRect() const
    {
        return QRectF( 0 , 0 , this->LineWidth , this->height );
    }


    int height;
    int LineWidth;
    int LineCountMod;
    int CallNumber;
    QString metin;
    QFont font;
    QTextEdit* textEdit;

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget)
    {

        int y = 0 ;
        CallNumber = 0;
        int PageNumber = 1;

        for( int i = 0 ; i < textEdit->document()->blockCount() ; i++ ){

            QTextBlock block = textEdit->document()->findBlockByNumber(i);
            QTextLayout layout(block);
            layout.setFont(font);

            layout.beginLayout();

            while( true ){
                QTextLine line = layout.createLine();
                if( !line.isValid() ){
                    break;
                }else{
                    if( CallNumber > 37 &&  (CallNumber-37) % LineCountMod == 0 ){
                        y += 300;
                        PageNumber++;
                    }
                    CallNumber++;
                    if( CallNumber == 37 ){
                        y += 300;
                        PageNumber++;
                    }

                    line.setLineWidth( LineWidth );
                    line.setPosition( QPointF( 0 , y ) );
                    y += line.height();
                }
            }
            this->height = y;
            layout.endLayout();
            layout.draw(painter,QPointF(0,0));
        }
    }
    void UPdate(){
        update(-50,-50 , LineWidth+50 , height+50);
    }
};

您参考该课程,如果“ ”包含。 我希望这有帮助。


0
投票

我通过手动检查

QTextLine

中的换行符解决了这个问题
bool ElidedLabelPrivate::doTextLayout(QTextLayout &text_layout, int width,
                                      int height) const {
  /// if height <= 0 - no height limit
  int line_spacing = QFontMetrics(text_layout.font()).lineSpacing();
  qreal height_used = 0;
  qreal width_used = 0;
  const QString &text = text_layout.text();

  while (true) {
    QTextLine line = text_layout.createLine();
    if (!line.isValid()) {
      return true;  // text fits available size
    }
    line.setLineWidth(width);
    // check for line breaks
    const QStringRef line_text =
        text.midRef(line.textStart(), line.textLength());
    if (line_text.contains('\n')) {
      line.setNumColumns(line_text.indexOf('\n') + 1);
    }
    
    line.setPosition(QPointF(0, height_used));
    height_used += line_spacing;
    width_used = std::max(width_used, line.naturalTextWidth());
    int current_pos = line.textStart() + line.textLength();
    bool need_next_line = current_pos < text_layout.text().length();
    bool can_insert_line =
        (height <= 0) || (height_used + line_spacing <= height);
    if (need_next_line && !can_insert_line) {
      return false;
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.