方法二:
重写代理painter方法,发送消息给QTableView重置行大小resizeRowToContents,然后代理会调用sizeHint(根据帮助文档上说此方法返回大小作为参考值),需要计算出内容所需高度(计算有两种方法请看代码)
优点:比方法一简单、代码少,只会计算可视行
缺点:如果数据是变化的,则一直在计算(可以优化已经计算过且字符串没有变化的就不再计算和重置大小)
QTableView*mTableView = new QTableView(false, this);
mTableView->horizontalHeader()->setVisible(true);
ItemDelegate *mDelegate = new ItemDelegate(mTableView);
mTableView->setItemDelegate(mDelegate);
connect(mDelegate, &ItemDelegate::SignalResizeRowHeight, mTableView, &QTableView::resizeRowToContents);
#pragma once
#include <QEvent>
#include <QPainter>
#include <QApplication>
#include <QStyledItemDelegate>
class ItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ItemDelegate(QObject* parent) :QStyledItemDelegate(parent)
{
connect(this, &DataStreamItemDelegate::SignalResizeRow, this, [=](const int32_t& h, const QModelIndex& index)
{
//算法:除第一列行最高
int col = index.column();
int row = index.row();
FXD << row <<" "<< col ;
if (col == 0)
{
mHeights.clear(); //每次重置行数据,保证行高可以增高或者缩小
if (mColumnsHeight.keys().contains(row))
{
return;
}
mRowMaxHeight = h;
mColumnsHeight.insert(row, h);
}
else
{
//得到除去第一列的行最大高度
if (mHeights.value(row) >= h)
{
mRowMaxHeight = mHeights.value(row);
}
else
{
mHeights.insert(row, h);
mRowMaxHeight = h;
}
//与第一列行高度比较得到最大高度,即为本行最大高度
if (mColumnsHeight.value(row) > mRowMaxHeight) //一般情况第一行内容最多
{
mRowMaxHeight = mColumnsHeight.value(row);
}
}
emit SignalResizeRowHeight(row);
});
}
virtual~ItemDelegate() {}
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
{
FXD;
QStyleOptionViewItem itemOption(option);
initStyleOption(&itemOption, index);
if (itemOption.state & QStyle::State_HasFocus)
{
itemOption.state &= ~QStyle::State_HasFocus; // 去除焦点虚线
}
if (itemOption.state & QStyle::State_MouseOver)
{
itemOption.state &= ~QStyle::State_MouseOver;
}
if (option.state.testFlag(QStyle::State_Selected))
{
itemOption.state &= ~QStyle::State_Selected;
}
if (!index.isValid())
{
return;
}
painter->save();
QStyledItemDelegate::paint(painter, itemOption, index);
painter->setPen(QPen(QBrush(QColor(0xD8, 0xD8, 0xD8)), HOR_LINE_WIDTH, ((QTableView*)tableView)->gridStyle()));
painter->drawLine(itemOption.rect.bottomLeft(), itemOption.rect.bottomRight());
painter->restore();
paint(painter, option, index);
if (option.rect.width() <= 0)
{
return;
}
QString data = index.model()->data(index, Qt::UserRole).value<QString>();
painter->save();
painter->setPen(QPen(Qt::black, 1, Qt::SolidLine));
painter->setFont(option.font);
QTextOption toption(Qt::AlignLeft);
toption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
painter->drawText(option.rect.adjusted(mPadding, mPadding, -mPadding, -mPadding), data, toption);
painter->restore();
//计算内容所需高度方法一
int col = index.column();
int row = index.row();
if (col == 0) //第一列只计算一次
{
if (!mColumnsHeight.keys().contains(row))
{
QRect rect = option.rect.adjusted(mPadding, 0, -mPadding, 0);
rect.setHeight(500);
painter->setFont(option.font);
rect = painter->boundingRect(rect, data, toption).toRect();
rect.setHeight(rect.height() + mPadding * 2);
emit SignalResizeRow(rect.height(), index);
}
}
else
{
QRect rect = option.rect.adjusted(mPadding, 0, -mPadding, 0);
rect.setHeight(500);
painter->setFont(option.font);
rect = painter->boundingRect(rect, data, toption).toRect();
rect.setHeight(rect.height() + mPadding * 2);
emit SignalResizeRow(rect.height(), index);
}
}
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override
{
if (option.rect.width() <= 0)
{
return QStyledItemDelegate::sizeHint(option, index);
}
FXD;
//计算内容所需高度方法二,此方法有一个弊端 [参考我这篇文章](https://blog.csdn.net/u011100345/article/details/115914781)
//QString data = index.model()->data(index, Qt::UserRole).value<QString>();
//QRect rect = option.rect.adjusted(mPadding,0,-mPadding,0);
//rect.setHeight(500);
//rect = QFontMetrics(option.font).boundingRect(rect, Qt::TextWordWrap | Qt::TextWrapAnywhere, data); //
//rect.setHeight(rect.height() + mPadding * 2);
QSize size = QStyledItemDelegate::sizeHint(option, index);
if (mRowMaxHeight > mRowHeight)
{
size.setHeight(mRowMaxHeight);
}
return size;
}
signals:
void SignalResizeRow(const int32_t& h, const QModelIndex& row)const;
void SignalResizeRowHeight(const int32_t& row);
private:
int32_t mPadding = 16; //内容上下左右空隙
int32_t mRowMaxHeight = 0;
QMap<int32_t, int32_t> mHeights; //其他列对应行最大高度
QMap<int32_t, int32_t> mColumnsHeight;//数据流第一列只计算一次存储用于后续比较<行号-高度>
};