尝试使用setWordWrap(true),但是仅对中文有效,对英文不会自动换行,最后只能用代理。
1.代理实现
class WordWrapDelegate : public QStyledItemDelegate
{
public:
using QStyledItemDelegate::QStyledItemDelegate;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
1.1进行中英文自动换行
void WordWrapDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
// 创建一个 QTextDocument 并设置其内容
QTextDocument doc;
//设置样式
QString html = QString(
"<div style='font-size: 16px;"
"font-family: Source Han Sans CN Regular;"
"font-weight: 400;"
"color:#FFFFFF; '>%1</div>"
).arg(opt.text);
doc.setHtml(html);
doc.setTextWidth(opt.rect.width());
//doc.setHtml(opt.text);//如果不设置样式,就直接写这一句
painter->save();
// 绘制背景(包括选中状态/鼠标悬停状态)
if ((opt.state & QStyle::State_Selected) || (opt.state & QStyle::State_MouseOver)) {
painter->fillRect(opt.rect, opt.palette.highlight());
}
else {
painter->fillRect(opt.rect, opt.palette.base());
}
// 调整 painter 的剪裁区域,以避免绘制超出单元格的内容
painter->setClipRect(opt.rect);
// 将文本绘制到单元格中
QRect textRect = opt.rect;
painter->translate(textRect.topLeft());
doc.drawContents(painter);
painter->restore();
}
QSize WordWrapDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
// 创建一个 QTextDocument 并设置其内容
QTextDocument doc;
//设置样式
QString html = QString(
"<div style='font-size: 16px;"
"font-family: Source Han Sans CN Regular;"
"font-weight: 400;"
"color:#FFFFFF; '>%1</div>"
).arg(opt.text);
doc.setHtml(html);
doc.setTextWidth(opt.rect.width());
//doc.setHtml(opt.text);
return QSize(doc.idealWidth(), doc.size().height());
}
1.2第一列添加复选框,并实现中英文自动换行
完全重绘,与部分重绘不太一样。
void WordWrapDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
painter->save();
// 绘制背景和高亮
painter->setClipRect(option.rect);
if ((option.state & QStyle::State_Selected) || (option.state & QStyle::State_MouseOver))
{
painter->fillRect(option.rect, option.palette.highlight());
}
else
{
painter->fillRect(option.rect, option.palette.base());
}
QRect textRect = option.rect;
// 绘制复选框
if (index.column() == 0)
{
QStyleOptionButton checkBoxOption;
QRect checkBoxRect = option.rect;
checkBoxRect.setWidth(option.rect.height()); // 让复选框变为正方形
checkBoxOption.rect = checkBoxRect;
checkBoxOption.state = QStyle::State_Enabled;
if (index.data(Qt::CheckStateRole).toBool())
{
checkBoxOption.state |= QStyle::State_On;
}
else
{
checkBoxOption.state |= QStyle::State_Off;
}
QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxOption, painter);
}
// 绘制文本
QTextDocument doc;
QString html = QString(
"<div style='font-size: 16px;"
"font-family: Source Han Sans CN Regular;"
"font-weight: 400;"
"color:#FFFFFF; '>%1</div>"
).arg(index.data(Qt::DisplayRole).toString());
doc.setHtml(html);
doc.setTextWidth(textRect.width());
// 设置文本块格式为中心对齐
QTextBlockFormat blockFormat;
if (index.column() == 0)
{
blockFormat.setAlignment(Qt::AlignLeft);
textRect.setLeft(textRect.left() + 20);
//设置边距,以防遮挡文字
QTextFrameFormat frameFormat;
frameFormat.setRightMargin(25);
QTextFrame *rootFrame = doc.rootFrame();
rootFrame->setFrameFormat(frameFormat);
}
else
{
blockFormat.setAlignment(Qt::AlignCenter);
}
painter->translate(textRect.topLeft());
doc.drawContents(painter);
painter->restore();
}
QSize WordWrapDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
// 创建一个 QTextDocument 并设置其内容
QTextDocument doc;
//设置样式
QString html = QString(
"<div style='font-size: 16px;"
"font-family: Source Han Sans CN Regular;"
"font-weight: 400;"
"color:#FFFFFF; '>%1</div>"
).arg(opt.text);
doc.setHtml(html);
doc.setTextWidth(opt.rect.width());
//doc.setHtml(opt.text);
QSize size = doc.size().toSize();
size.setHeight(qMax(size.height(), opt.fontMetrics.height()));
// 如果第一列,则添加复选框空间
if (index.column() == 0) {
size.rwidth() += 20; // 复选框宽度为20
}
return size;
}
2代理使用
//代理
WordWrapDelegate *delegate = new WordWrapDelegate(tableWidget);
tableWidget->setItemDelegate(delegate);
//插入数据
...
//设置自适应高度、宽度
tableWidget->setWordWrap(true);
tableWidget->resizeColumnsToContents();
tableWidget->resizeRowsToContents();