参考:
C++ GUI Programming with Qt 4, Second Edition
本地环境:
win10专业版,64位,Qt5.12
所有代码已经跑通。
仅供个人记录、积累。
基础版
效果
实现
如何获取QTableWidget的默认行高?
double getDefaultRowHeight(QTableWidget* table) {
QFontMetrics fontMetrics(table->font());
return fontMetrics.height() * 1.25; // 一般是字体大小的1.25倍
}
代码
myTableWidget->setRowCount(nrows); // 设置一下行数
// 设置整个表格可以排序
myTableWidget->setSortingEnabled(true);
double defaultRowHeight = getDefaultRowHeight(myTableWidget);
// 循环,填充每一行. dfo是包含信息的一个对象
for (int i = 0; i < nrows; i++) {
// 第一列,先创建内嵌的表格
QTableWidget *nestedTable = new QTableWidget;
nestedTable->setRowCount(xxx);
nestedTable->setColumnCount(3);
// 不显示表头和列头
nestedTable->horizontalHeader()->setVisible(false);
nestedTable->verticalHeader()->setVisible(false);
// 这句不知道为啥不能无框线
//nestedTable->setStyleSheet("QTableWidget { border: none; }");
// fill name
QTableWidgetItem *name = new QTableWidgetItem();
// 设置字体
name->setTextColor(QColor(Qt::darkBlue));
name->setText(XXX);
// 填充第一行
nestedTable->setItem(0, 0, name);
int kc = 1;
// 循环填充细节
for (QHash<QString, QString>::iterator it = Details.begin();
it != Details.end(); it ++) {
QTableWidgetItem *key = new QTableWidgetItem();
QFont myfont;
myfont.setBold(true); // 加粗
key->setFont(myfont);
key->setText(it.key());
// 填充内容
nestedTable->setItem(kc, 0, key);
nestedTable->setItem(kc, 1, new QTableWidgetItem("="));
QTableWidgetItem *val = new QTableWidgetItem(it.value());
nestedTable->setItem(kc, 2, val);
kc ++; // 继续创建下一行
}
// 设置列宽
nestedTable->setColumnWidth(1, 10);
nestedTable->setColumnWidth(2, 300);
// 为了占满单元格
nestedTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
myTableWidget->setCellWidget(i, 0, nestedTable);
// 设置行高
myTableWidget->setRowHeight(i, static_cast<int>((kc + 2) * defaultRowHeight));
myTableWidget->setColumnWidth(0, 400);
// position
QTableWidgetItem *pitem = new QTableWidgetItem(xxx);
myTableWidget->setItem(i, 1, pitem);
// 其他列内容填充
...
}
现在还存在单元格里长字符串重叠的问题,可以通过调整行高改善。不过我的项目最后没用这个方案,所以没继续优化。
无边框版
效果
实现
先写模型。其中数据中的key做列名,val做内容。
class FeatureTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit FeatureTableModel(QObject* parent = nullptr)
: QAbstractTableModel(parent)
{
}
void setData(QMap<QString, QString> other, QString name) {
// 刷新数据
beginResetModel();
this->m_data = other;
this->name = name;
endResetModel();
}
QMap<QString, QString> getData() {
return this->m_data;
}
QString getName() {
return this->name;
}
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
{
if (role == Qt::DisplayRole)
{
if (orientation == Qt::Horizontal)
{
return QVariant(this->name); // 返回Name
}
else if (orientation == Qt::Vertical)
{
return QVariant((this->m_data.begin() + section).key());
}
}
if (role == Qt::TextAlignmentRole) {
return int(Qt::AlignLeft | Qt::AlignVCenter);
}
return QAbstractTableModel::headerData(section, orientation, role);
}
int rowCount(const QModelIndex& parent = QModelIndex()) const override
{
return m_data.size();
}
int columnCount(const QModelIndex& parent = QModelIndex()) const override
{
return 1;
}
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
{
// index不合法返回空的
if (!index.isValid())
return QVariant();
if (role == Qt::TextAlignmentRole) {
return int(Qt::AlignLeft | Qt::AlignVCenter);
} else if (role == Qt::DisplayRole) {
return (m_data.begin() + index.row()).value();
}
return QVariant();
}
Qt::ItemFlags flags(const QModelIndex& index) const override
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override
{
if (index.isValid() && role == Qt::EditRole) {
//m_data.replace(index.row(), value.toString());
//emit dataChanged(index, index);
return true;
}
return false;
}
private:
QMap<QString,QString> m_data; // key-val
QString name;
};
然后写使用部分:
// 总表
QTableWidget *table = new QTableWidget;
table->setRowCount(2);
table->setColumnCount(2);
QTableView *nestedTableView = new QTableView;
// 模型
FeatureTableModel* nestedModel = new FeatureTableModel;
QMap<QString, QString> map = {{"a","1"}, {"b", "2"}, {"c", "3"}};
nestedModel->setData(map, "Name");
nestedTableView->setModel(nestedModel);
// 去掉框线
nestedTableView->setShowGrid(false);
// 设置表头的格式
nestedTableView->horizontalHeader()->setStyleSheet("text-align:left; color:blue;");
// 设置表格自适应内容大小
nestedTableView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
// 设置自适应内容边界
//nestedTableView->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
// 动态设置列宽和行高
nestedTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
nestedTableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
// 自动调整行高和列宽
nestedTableView->resizeRowsToContents();
nestedTableView->resizeColumnsToContents();
// 嵌套的表格加入总表
table->setCellWidget(0, 0, nestedTableView);
// 填充其他内容
table->setItem(0, 1, new QTableWidgetItem("aaaa"));
table->setItem(1, 0, new QTableWidgetItem("aaaa"));
table->setItem(1, 1, new QTableWidgetItem("aaaa"));
// table也要自动调整,不然扁扁的不好看
table->resizeRowsToContents();
table->resizeColumnsToContents();
table->show();