QtCreator QTableView用法大全,隐藏列,添加关系表,设置列宽,设置显示列名(持续添加)

本文详细介绍了如何使用QSqlRelationalTableModel整合SQL模型与视图,包括设置关系表、视图委托、字段名、查询操作、隐藏列、设置列宽等关键步骤。

基本用法

//定义表模型

QSqlRelationalTableModel *tableModel;

    tableModel->setTable("baoxiudan");

    //设置关系表(外键)
    tableModel->setRelation(2,QSqlRelation("department","departmentId","departmentName"));
    //设置关系表视图委托
    ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));

      //设置字段名,列名
    tableModel->setHeaderData(0,Qt::Horizontal,"报修单号");


    tableModel->select(); //查询表内容

        //设置字段名,列名
tableModel->setHeaderData(0,Qt::Horizontal,"报修单号");


    //绑定模型与视图
    ui->tableView->setModel(tableModel);


    //隐藏不需要显示的列

    for (int i = 9; i < tableModel->columnCount(); i++) {
        ui->tableView->setColumnHidden(i,true);
    }





    //设置列宽
    ui->tableView->setColumnWidth(2,150);
    ui->tableView->setColumnWidth(3,150);
    ui->tableView->setColumnWidth(4,150);
    ui->tableView->setColumnWidth(5,150);



QSqlRelationalTableModel *tableModel;




<think>我们之前已经实现了水平表头的多行设置,现在用户要求对垂直表头(行表头)进行类似设置:将第七垂直表头设置为两行(实际上是针对第七行,因为垂直表头控制行)。但注意,垂直表头通常是控制行的,而用户描述为“第七垂直表头”,这里可能存在歧义。通常: - 水平表头(horizontalHeader)控制的表头。 - 垂直表头(verticalHeader)控制行的表头。 用户描述:“将第七垂直表头设置为两行”,这里可能是指垂直表头(即行表头)的第七行(row index=6)设置为两行?但垂直表头本身是每行一个表头项,现在要求将第七行的垂直表头项拆分成上下两个部分(上面一个单元格,下面三个单元格?)。这并不常见,因为垂直表头通常只有一多行(每行一个表头项)。 但是,根据用户要求,我们理解为:在垂直表头(行表头)的第七行(即第7行)处,希望该行的行表头显示为两行(即两个高度的表头项),并且上面一行是一个单元格,下面一行分三(即该行表头内部再分三)。这实际上意味着我们需要在垂直表头上实现一个合并单元格的效果,但垂直表头默认不支持多行。 由于QHeaderView(包括垂直表头)默认是单行或单的,不支持内部合并单元格。因此,我们需要采用类似水平多行表头的方案:使用额外的QTableView来模拟垂直表头。 然而,用户要求的是垂直表头(行表头)的特定行(第七行)设置为两行,这实际上改变了整个行表头的结构。我们可能需要重新设计,将整个行表头用一个独立的QTableView来模拟,并且这个模拟的行表头需要有两:第一对应上面一行(一个单元格),第二对应下面一行(分三?但这里用户要求是下面一行分三,但垂直表头通常只有一,所以这里可能是指将第七行的行表头拆分成两行,其中第二行又拆分成三?)。 这实际上非常复杂,因为垂直表头通常是纵向的。我们可能需要将主表的垂直表头隐藏,然后在左侧放置一个额外的QTableView作为伪垂直表头,并且这个伪垂直表头需要有两:第一用于显示上面一行的内容(合并第七行对应的位置),第二用于显示下面一行的内容(再拆分成三行?)。但这样会变得非常混乱。 另一种思路:用户可能是指水平表头的第七?但用户明确写了“垂直表头”。这里我们按照垂直表头(行表头)来理解。 ### 重新理解需求 用户希望:在QTableView的垂直表头(行表头)中,将第七行(索引为6)的表头单元格拆分成上下两个部分(两行),上面部分是一个单元格,下面部分再分成三(即三个单元格)。这相当于在垂直表头中,第七行的高度被分成两行,并且下面一行又分成三。但垂直表头本身只有一,所以下面一行的三实际上是指在该行表头内部再画三个小单元格。 然而,Qt的垂直表头(QHeaderView)并不支持这种内部拆分。因此,我们需要用两个QTableView来模拟: 1. 一个作为伪垂直表头(位于主表左侧),它有两:第一用于显示上面部分(一个单元格),第二用于显示下面部分(再分成三行?但这里用户要求下面部分分三,所以伪垂直表头的第二实际上需要再分成三?)。这会导致伪垂直表头有两,其中第二又需要分成三?这显然不合理。 ### 另一种方案:自定义委托 我们可以在垂直表头使用自定义绘制,将第七行的表头单元格绘制成两行,并在下面一行内绘制三个小单元格。但这需要重写QHeaderView的绘制事件,并且还要处理鼠标事件(如点击小单元格时的响应)。 ### 简化需求 考虑到复杂度,这里我们假设用户希望将第七行的垂直表头(行表头)拆分成上下两个单元格(两行),但不要求再分(因为垂直表头只有一,分没有意义)。如果用户确实要求分,那么可能是指将垂直表头的第七行拆分成多个部分,但垂直方向分并不常见。 ### 用户需求再确认 根据用户描述:“将第七垂直表头设置为两行,上面一行为一个单元格,下面一行分三”。这里“第七垂直表头”可能是指第七行的垂直表头。而“分三”可能是指下面一行被分成三个小单元格(水平排)。所以,整个第七行的垂直表头被拆分成两个部分:上面一个单元格(跨整个度),下面一行包含三个水平排的小单元格。 ### 实现方案 1. 隐藏主表的垂直表头。 2. 在主表左侧放置一个额外的QTableView作为伪垂直表头(pseudoVerticalHeader)。这个伪垂直表头有2(对应上面一行和下面一行?)和与主表相同的行数(但只需要在第七行显示特殊结构,其他行正常显示)。 3. 伪垂直表头的模型需要设置行数与主表相同,数为2(第一用于上面一行,第二用于下面一行)。然后,在第七行,第一显示上面一行的内容,第二显示下面一行的内容(但下面一行又需要分成三,所以第二实际上需要再拆分?)。 这变得非常复杂,因为伪垂直表头本身是一个表格,它的第二如何再分成三?这实际上需要嵌套表格,技术上不可行。 ### 替代方案:使用QTableWidget的setCellWidget 如果我们使用QTableWidget,可以在垂直表头的位置(实际上是行号所在的位置)放置一个自定义控件。但垂直表头本身不能放置控件。 ### 推荐方案:自定义垂直表头 子类化QHeaderView(垂直表头),重写paintSection方法,在绘制第七行时,将其绘制成上下两个部分,上面部分绘制一个单元格,下面部分绘制三个小单元格。同时,重写sizeHint和sectionSizeFromContents来调整高度(因为第七行需要更高)。 ### 示例代码(自定义垂直表头): ```cpp class CustomVerticalHeader : public QHeaderView { Q_OBJECT public: CustomVerticalHeader(QWidget *parent = nullptr) : QHeaderView(Qt::Vertical, parent) { // 设置第七行(索引6)需要特殊绘制 setSectionsClickable(true); } protected: void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override { if (logicalIndex == 6) { // 第七行 // 将整个rect分成上下两部分:上面部分占1/2高度,下面部分占1/2高度,下面部分再分成三 int totalHeight = rect.height(); int topHeight = totalHeight / 2; int bottomHeight = totalHeight - topHeight; // 绘制上面部分(一个单元格,跨整个度) QRect topRect(rect.x(), rect.y(), rect.width(), topHeight); painter->fillRect(topRect, Qt::lightGray); painter->drawRect(topRect); painter->drawText(topRect, Qt::AlignCenter, "Top"); // 绘制下面部分(分成三个小单元格) int colWidth = rect.width() / 3; for (int i = 0; i < 3; ++i) { QRect cellRect(rect.x() + i * colWidth, rect.y() + topHeight, colWidth, bottomHeight); painter->fillRect(cellRect, Qt::white); painter->drawRect(cellRect); painter->drawText(cellRect, Qt::AlignCenter, QString("Sub%1").arg(i+1)); } } else { // 其他行正常绘制 QHeaderView::paintSection(painter, rect, logicalIndex); } } QSize sizeHint() const override { // 设置第七行的高度为其他行的两倍 QSize sz = QHeaderView::sizeHint(); if (orientation() == Qt::Vertical) { // 获取默认行高 int defaultHeight = sz.height(); // 第七行需要更高,比如是其他行的两倍 // 注意:这里只是示例,实际需要根据模型索引调整 return QSize(sz.width(), defaultHeight * 2); } return sz; } QSize sectionSizeFromContents(int logicalIndex) const override { if (logicalIndex == 6) { // 第七行的高度设为其他行的两倍 QSize baseSize = QHeaderView::sectionSizeFromContents(logicalIndex); return QSize(baseSize.width(), baseSize.height() * 2); } return QHeaderView::sectionSizeFromContents(logicalIndex); } }; ``` ### 使用自定义垂直表头 ```cpp QTableView *tableView = new QTableView; CustomVerticalHeader *verticalHeader = new CustomVerticalHeader; tableView->setVerticalHeader(verticalHeader); ``` ### 注意事项 - 此方案仅改变了第七行的绘制效果,但并没有改变第七行内部事件处理(如点击三个小单元格的不同响应)。如果需要处理事件,还需重写mousePressEvent等。 - 第七行的高度需要是其他行的两倍(或根据需求调整)。 §§相关问题§§ 1. 如何在Qt中自定义QHeaderView的绘制以实现复杂的表头效果? 2. 如何为QTableView的特定行设置不同的行高? 3. 在自定义表头中如何处理鼠标点击事件以实现交互功能? 4. 除了自定义绘制,还有哪些方法可以实现QTableView的多级表头? 5. 如何确保自定义表头在调整行高或时保持与主表同步?</think>在 Qt Creator 中为 QTableView 的垂直表头(行表头)设置第七(实际是第七行)为两行结构(上面一个单元格,下面分三),可以通过自定义垂直表头实现。以下是完整解决方案: ### 实现步骤 1. **子类化 QHeaderView**:创建自定义垂直表头类 2. **重写关键方法**: - `paintSection()`:处理特殊行的绘制 - `sectionSizeFromContents()`:调整特殊行高度 - `mousePressEvent()`:处理特殊单元格的点击 3. **设置自定义表头**:应用到 QTableView ### 完整代码实现 ```cpp #include <QHeaderView> #include <QPainter> #include <QMouseEvent> class CustomVerticalHeader : public QHeaderView { Q_OBJECT public: explicit CustomVerticalHeader(QWidget *parent = nullptr) : QHeaderView(Qt::Vertical, parent) { setSectionsClickable(true); setHighlightSections(true); } protected: void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override { if (logicalIndex == 6) { // 第七行(索引从0开始) // 1. 绘制顶部单元格(跨整个度) QRect topRect(rect.x(), rect.y(), rect.width(), rect.height() / 2); painter->fillRect(topRect, QColor(240, 240, 240)); painter->drawRect(topRect); painter->drawText(topRect, Qt::AlignCenter, "顶部标题"); // 2. 绘制底部三个单元格 int colWidth = rect.width() / 3; for (int i = 0; i < 3; ++i) { QRect cellRect(rect.x() + i * colWidth, rect.y() + rect.height() / 2, colWidth, rect.height() / 2); painter->drawRect(cellRect); painter->drawText(cellRect, Qt::AlignCenter, QString("子%1").arg(i + 1)); } } else { // 其他行正常绘制 QHeaderView::paintSection(painter, rect, logicalIndex); } } QSize sectionSizeFromContents(int logicalIndex) const override { if (logicalIndex == 6) { // 第七行高度设为其他行的两倍 QSize baseSize = QHeaderView::sectionSizeFromContents(logicalIndex); return QSize(baseSize.width(), baseSize.height() * 2); } return QHeaderView::sectionSizeFromContents(logicalIndex); } void mousePressEvent(QMouseEvent *event) override { int section = logicalIndexAt(event->pos()); if (section == 6) { // 计算点击位置在第七行的哪个子区域 QRect rect = sectionViewportPosition(6); int yInSection = event->pos().y() - rect.y(); if (yInSection > rect.height() / 2) { // 计算点击了哪个子 int colWidth = rect.width() / 3; int subCol = (event->pos().x() - rect.x()) / colWidth; qDebug() << "点击了第七行的子:" << subCol + 1; emit subHeaderClicked(6, subCol); return; } } QHeaderView::mousePressEvent(event); } signals: void subHeaderClicked(int row, int subIndex); }; // 在QTableView中使用 QTableView *tableView = new QTableView; CustomVerticalHeader *customHeader = new CustomVerticalHeader; tableView->setVerticalHeader(customHeader); // 连接信号 QObject::connect(customHeader, &CustomVerticalHeader::subHeaderClicked, [](int row, int subIndex) { qDebug() << "行:" << row << "子索引:" << subIndex; }); ``` ### 关键点说明 1. **特殊行识别**:`logicalIndex == 6` 对应第七行(索引从0开始) 2. **高度处理**: - 通过 `sectionSizeFromContents()` 将第七行高度设为两倍 - 在 `paintSection()` 中将行垂直分为两部分 3. **事件处理**: - 顶部区域:触发标准行选择 - 底部子:发射 `subHeaderClicked` 信号 4. **样式定制**: - 顶部单元格:灰色背景 - 底部子:三等分绘制 - 可通过修改绘制代码自定义样式 ### 注意事项 1. 需要设置模型的行数至少为7行 2. 调整大小时需调用 `resizeSections(QHeaderView::ResizeToContents)` 3. 如需水平表头也有类似效果,需单独实现水平表头的自定义
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值