You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让包含短横线的文本在QStyledItemDelegate绘制时自动换行

问题原因

Qt的Qt::TextWordWrap标记仅支持在空格、换行符这类默认断字点处换行,日期字符串里的-、:不属于默认断字字符,所以整段日期会被识别为单个超长单词,宽度不足时直接裁切而非换行,和推测的触发原因一致。

解决方案

方案1:插入零宽空格(最简单,无显示副作用)

在日期的分隔符后插入零宽空格\u200B,这个字符不会在界面显示,但会被Qt识别为合法断字点,无需修改其他绘制逻辑:

int flags = Qt::AlignCenter | Qt::TextWordWrap | Qt::TextJustificationForced;
switch (index.column())
{
case TimeRole:
{
    int boxW = 16, space = 5, leftSpace = 30;
    QRect textRect = QRect(rect.left() + leftSpace + boxW + space, rect.top(), rect.width() - boxW - space - m_space - leftSpace, rect.height());

    QDateTime time = QDateTime::fromMSecsSinceEpoch(model->m_eventTime);
    QString timeStr = time.toString("yyyy-MM-dd HH:mm:ss");
    // 新增:给分隔符后加零宽空格,支持任意位置换行
    timeStr.replace("-", "-\u200B").replace(":", ":\u200B");
    painter->drawText(textRect, flags, timeStr);
    break;
}
}

方案2:手动用QTextLayout计算换行(不修改原字符串)

如果不想修改原始日期字符串,可以手动控制换行逻辑:

// 省略前面textRect计算、timeStr获取的逻辑
QTextLayout textLayout(timeStr, painter->font());
textLayout.setCacheEnabled(true);

QTextOption textOption = textLayout.textOption();
textOption.setAlignment(Qt::AlignCenter);
textLayout.setTextOption(textOption);

int textWidth = textRect.width();
textLayout.beginLayout();
qreal height = 0;
while (true) {
    QTextLine line = textLayout.createLine();
    if (!line.isValid()) break;
    line.setLineWidth(textWidth);
    height += line.height();
    line.setPosition(QPointF(0, height));
}
textLayout.endLayout();

// 居中偏移计算
qreal yOffset = (textRect.height() - height) / 2;
painter->save();
painter->translate(textRect.left(), textRect.top() + yOffset);
textLayout.draw(painter, QPointF(0, 0));
painter->restore();

额外注意事项

如果换行后文本高度超过原单元格行高,还需要重写QStyledItemDelegate的sizeHint方法,根据文本内容计算实际需要的单元格高度,避免上下内容被裁切。

错误效果展示

显示错误

内容的提问来源于stack exchange,提问作者Tiina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 23:24:01