QPainter再指定区域内绘制文本并自动换行

在Qt编程中,自定义绘制控件时可能会遇到文本超出绘制区域的问题。文章介绍了三种实现文本换行的方法:使用drawText函数配合Qt::TextWordWrap标志,通过QTextOption设置换行模式,以及利用QTextDocument和QTextLayout进行布局。这些方法允许在固定宽度区域内自适应地显示文本,支持不同类型的换行策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在自定义绘制控件时,经常遇到文本超过绘制区域的情况,容易想到的办法显示部分文字和换行,一下介绍如何实现换行

方式一

//drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect = nullptr)
/*
	The flags argument is a bitwise OR of the following flags:
    Qt::AlignLeft
    Qt::AlignRight
    Qt::AlignHCenter
    Qt::AlignJustify
    Qt::AlignTop
    Qt::AlignBottom
    Qt::AlignVCenter
    Qt::AlignCenter
    Qt::TextDontClip
    Qt::TextSingleLine
    Qt::TextExpandTabs
    Qt::TextShowMnemonic
    Qt::TextWordWrap
    Qt::TextIncludeTrailingSpaces
*/
//适合固定区域文字自动换行模式
//eg:
QRectF rect(0,0,300,300);
QString text = "this is text";
painter->drawText(rect, Qt::TextWordWrap, text);

方式二

/*
void drawText(const QRectF &rectangle, const QString &text, const QTextOption &option = QTextOption())
这种方式可以指定文本换行的位置,比如任意位置换行,或者单词末尾换行

QTextOption::NoWrap
QTextOption::WordWrap
QTextOption::ManualWrap
QTextOption::WrapAnywhere
QTextOption::WrapAtWordBoundaryOrAnywhere

*/
//eg:
QRectF rect(0,0,300,300);
QString text = "this is text";
QTextOption option;
option.setWrapMode(QTextOption::WrapAnywhere)
painter->drawText(rect, Qt::TextWordWrap, option);

方式三

QPainter painter(this);
QTextOption option;
option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); // 设置自动换行模式
QString text = "This is a long text that needs to be broken into multiple lines.";
QTextDocument doc;
doc.setDefaultTextOption(option);
doc.setPlainText(text);
QTextLayout layout(doc);
layout.beginLayout();
QTextLine line = layout.createLine();
int y = 0;
while (line.isValid()) 
{
    line.setLineWidth(200);
    line.setPosition(QPointF(0, y));
    y += line.height();
    line = layout.createLine();
}
layout.endLayout();

layout.draw(&painter, QPointF(0, 0));

扩展

根据给定的文字长度,以固定的宽度区域,自适应高度绘制文本

//先计算出文本的宽度,和指定宽度比较,小于自定宽度直接绘制,否则需要计算换几行,指定高度
QPainter painter(this);
QFontMetrics metrics(painter.font());
QString text = "This is a long text that needs to be broken into multiple lines";
int textwidth = metrics.horizontalAdvance(text);	//获取文本的宽度
int rectWidth = 300;	//指定绘制宽度
int height = metrics.height();	//获取字体高度
if(textwidth <= rectwidth)
{//能够容纳,直接绘制
    QRect rect(0,0,rectwidth,height);
    painter.drawText(rect,Qt::AlignCenter,text);
}
else
{
    //计算需要显示几行
    int index = 0;
    QString temp = text;
    while(true)
    {
        auto temp1 = metrics.elidedText(temp,Qt::ElideRight,rectwidth);	//截断文字
        if(temp1.isEmpty()) break;
        
        index++;
        temp1 = temp1.remove("…");	//删除截断符号
        temp = temp.remove(temp1);
    }
    
    int _height = index*height;
    QRect rect(0,0,rectwidth,_height);
    QTextOption option;
    option.setWrapMode(QTextOption::WrapAnywhere)
    painter->drawText(rect, Qt::TextWordWrap, option);
    
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值