qt5-入门-QTableWidget-嵌套的表格

参考:
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();
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值