考核:QTableWidget开发[折叠/展开单元格QTableWidgetItem]

简介: 该软件模块是一个复杂的表格窗口,用于展示方案和装备信息。用户可以根据名称搜索并滚动到对应的方案。每个方案可以展开和折叠,显示方案的挂载总量和挂载配置。

@TOC

效果

演示.gif

要求

一、功能概述

image.png

二、功能

image.png

三、关系

image.png

FATable 表

CREATE TABLE fatable (idFA INTEGER,nameId TEXT,equipId TEXT,equipNum INTEGER);

1689405212640.png

idFA nameId equipId equipNum
1 A1001 9001 4
1 A1001 9003 1
2 A1001 9002 6
2 A1001 9020 8
1 B2001 9002 10
1 B2001 9004 1
2 B2001 9006 4
2 B2001 9008 2
2 B2001 9010 4
1 A1002 9002 16
2 A1002 9003 1
3 A1002 9020 16
3 A1002 9010 8
1 B2002 9002 18
2 B2002 9006 4
2 B2002 9008 4
2 B2002 9010 8
3 B2002 9003 1
3 B2002 9004 1

NTable 表

CREATE TABLE nTable (name VARCHAR(100),nameId VARCHAR(10),classify INT);

1689406379740.png

name nameId classify
奥迪A6L A1001 2
宝马X7 A1002 2
迈巴赫S600 B2001 3
劳斯莱斯-库里南 B2002 3
Dynaudio丹拿 9001 4
柏林之声 9002 4
前天窗 9003 5
后天窗 9004 5
前排气囊 9006 6
后排气囊 9008 6
侧面气囊 9010 2
空调口 9020 2

CTable 表

CREATE TABLE cTable (classify INT,className VARCHAR(100));

1689406552048.png

classify className
1 B级车中型车
2 C级车中大型车
3 S级车顶级豪华车
4 音响
5 天窗
6 气囊
7 空调

实现

infos.h


#ifndef INFOS_H
#define INFOS_H
#include<QString>
#include<QVector>
struct FATable {
   
   
    int idFA;               //方案ID
    QString nameId;         //名称ID
    QString equipId;        //装备ID
    int equipNum;           //装备数量
};
inline QVector<FATable> faTable = {
   
   
    {
   
   1, "A1001", "9001",4},
    {
   
   1, "A1001", "9003",1},
    {
   
   2, "A1001", "9002",6},
    {
   
   2, "A1001", "9020",8},
    {
   
   1, "B2001", "9002",10},
    {
   
   1, "B2001", "9004",1},
    {
   
   2, "B2001", "9006",4},
    {
   
   2, "B2001", "9008",2},
    {
   
   2, "B2001", "9010",4},
    {
   
   1, "A1002", "9002",16},
    {
   
   2, "A1002", "9003",1},
    {
   
   3, "A1002", "9020",16},
    {
   
   3, "A1002", "9010",8},
    {
   
   1, "B2002", "9002",18},
    {
   
   2, "B2002", "9006",4},
    {
   
   2, "B2002", "9008",4},
    {
   
   2, "B2002", "9010",8},
    {
   
   3, "B2002", "9003",1},
    {
   
   3, "B2002", "9004",1},
    };

struct NTable {
   
   
    QString name;           //装备名称
    QString nameId;         //装备ID
    int classify;           //分类ID
};
inline QVector<NTable> nTable = {
   
   
    {
   
   "奥迪A6L", "A1001", 2},
    {
   
   "宝马X7", "A1002", 2},
    {
   
   "迈巴赫S600", "B2001",3},
    {
   
   "劳斯莱斯-库里南", "B2002",3},
    {
   
   "Dynaudio丹拿", "9001", 4},
    {
   
   "柏林之声", "9002",4},
    {
   
   "前天窗", "9003",5},
    {
   
   "后天窗", "9004", 5},
    {
   
   "前排气囊", "9006", 6},
    {
   
   "后排气囊", "9008", 6},
    {
   
   "侧面气囊", "9010", 2},
    {
   
   "空调口", "9020", 2},
};
struct CTable {
   
   
    int classify;           //分类ID
    QString className;      //分类名称
};
inline QVector<CTable> cTable = {
   
   
    {
   
   1, "B级车中型车"},
    {
   
   2, "C级车中大型车"},
    {
   
   3, "S级车顶级豪华车"},
    {
   
   4, "音响"},
    {
   
   5, "天窗"},
    {
   
   6, "气囊"},
    {
   
   7, "空调"}
};
#endif // INFOS_H

main.cpp

ComplexTableWidget w;
w.show();

complextablewidget.h

#ifndef COMPLEXTABLEWIDGET_H
#define COMPLEXTABLEWIDGET_H
#include <QDialog>
class SchemeDialog;
QT_BEGIN_NAMESPACE
namespace Ui {
   
    class ComplexTableWidget; }
QT_END_NAMESPACE
class ComplexTableWidget : public QDialog

{
   
   
    Q_OBJECT

public:
    ComplexTableWidget(QWidget *parent = nullptr);
    ~ComplexTableWidget();

private:
    Ui::ComplexTableWidget *ui;
    void initUI();
    QStringList m_schemeItems;
private slots:
    void on_searchBtn_clicked();
};
#endif // COMPLEXTABLEWIDGET_H

complextablewidget.cpp

#include "complextablewidget.h"
#include "ui_complextablewidget.h"
#include<QPushButton>
#include<QSplitter>
#include<QLabel>
#include<QDebug>
#include "schemedialog.h"
#include "infos.h"
#include<QDebug>
ComplexTableWidget::ComplexTableWidget(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::ComplexTableWidget)
{
   
   
    ui->setupUi(this);
    initUI();
}

ComplexTableWidget::~ComplexTableWidget()
{
   
   
    delete ui;
}

void ComplexTableWidget::initUI()
{
   
   
    setWindowFlags(Qt::Dialog|Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint);
    ui->searchLEdit->setPlaceholderText("请输入名称");
    ui->tableWidget->horizontalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setSelectionBehavior(QAbstractItemView::SelectRows);   // 选择行为:行
    ui->tableWidget->horizontalHeader()->setSelectionMode(QAbstractItemView::SingleSelection);  // 选择模式:单选
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    ui->tableWidget->setColumnCount(1);
    ui->tableWidget->setRowCount(0);
    m_schemeItems.clear();
    QMap<QString,QList<FATable>> nameIdMap;
    for (auto &it:faTable) {
   
   
        nameIdMap[it.nameId].append(it);
    }
    QMap<QString,QString> idToNameMap;
    for (auto &it:nTable) {
   
   
        idToNameMap.insert(it.nameId,it.name);
    }

    for (auto &namekey:nameIdMap.keys())
    {
   
   
        m_schemeItems.append(idToNameMap.value(namekey));
        int row=ui->tableWidget->rowCount();

        ui->tableWidget->insertRow(row);

        auto *schemeDialog=new SchemeDialog(namekey, nameIdMap.value(namekey));
        // 将父级对话框设置为单元格的组件
        ui->tableWidget->setCellWidget(row, 0, schemeDialog);
        // 设置单元格的行高以适应内容
        ui->tableWidget->resizeRowsToContents();

        connect(schemeDialog, &SchemeDialog::isFoldSignal, [this]() {
   
   
            qDebug()<<"点击";
            // 设置单元格的行高以适应内容
            ui->tableWidget->resizeRowsToContents();
        });
    }

}

void ComplexTableWidget::on_searchBtn_clicked()
{
   
   
    QString search = ui->searchLEdit->text();
    if(search.isEmpty())
        return;
    int row = m_schemeItems.indexOf(search);
    if(row==-1)
        return;

    auto item=static_cast<SchemeDialog*>(ui->tableWidget->cellWidget(row,0));
    item->setFoldView(false);
    ui->tableWidget->setCurrentCell(row,0);
    // 设置单元格的行高以适应内容
    ui->tableWidget->resizeRowsToContents();
}

schemedialog.h

#ifndef SCHEMEDIALOG_H
#define SCHEMEDIALOG_H

#include <QDialog>
#include "infos.h"
namespace Ui {
   
   
class SchemeDialog;
}

class SchemeDialog : public QDialog
{
   
   
    Q_OBJECT

public:
    explicit SchemeDialog(QWidget *parent = nullptr);
    SchemeDialog(const QString &name,const QList<FATable> currNameInfos,QWidget *parent = nullptr);
    ~SchemeDialog();

    void initUI();
    void updataTabel();
    void updataFoldBtnIcon(bool);
    void setFoldView(bool);
signals:
    void isFoldSignal(bool);

private slots:
    void on_foldBtn_clicked();

private:
    Ui::SchemeDialog *ui;
    const QString m_name;
    const QList<FATable> m_currNameInfos;
};
#endif // SCHEMEDIALOG_H

schemedialog.cpp

#include "schemedialog.h"
#include "ui_schemedialog.h"

#include<QDebug>
namespace{
   
   
    enum EMountCol{
   
   
                MountID=0,      //方案ID
                MountSum,       //挂载总量
                MountConfig     //挂载配置
    };
    QVariantMap idToNameMap;    //通过装备ID获取装备名称
}
SchemeDialog::SchemeDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SchemeDialog)
{
   
   
    ui->setupUi(this);
}

SchemeDialog::SchemeDialog(const QString &name, const QList<FATable> currNameInfos, QWidget *parent)
    :QDialog(parent),
    ui(new Ui::SchemeDialog),
    m_name(name),
    m_currNameInfos(currNameInfos)
{
   
   
    ui->setupUi(this);
    initUI();
    updataTabel();
}

SchemeDialog::~SchemeDialog()
{
   
   
    delete ui;
}

void SchemeDialog::initUI()
{
   
   
    setWindowFlags(Qt::FramelessWindowHint);  // 设置无边框样式
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->horizontalHeader()->setSelectionBehavior(QAbstractItemView::SelectRows);   // 选择行为:行
    ui->tableWidget->horizontalHeader()->setSelectionMode(QAbstractItemView::SingleSelection);  // 选择模式:单选
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
    ui->tableWidget->verticalHeader()->setVisible(false);

    idToNameMap.clear();
    QVariantMap idToClassifyMap;
    for (auto &var:nTable) {
   
   
        idToNameMap.insert(var.nameId,var.name);
        idToClassifyMap.insert(var.nameId,var.classify);
    }
    ui->nameLabel->setText(idToNameMap.value(m_name).toString());

    QMap<int,QString> idKeyMap;
    for (auto &var:cTable) {
   
   
        idKeyMap.insert(var.classify,var.className);
    }
    ui->typeLabel->setText(idKeyMap.value(idToClassifyMap[m_name].toInt()));
}

void SchemeDialog::updataTabel()
{
   
   
    ui->tableWidget->setRowCount(0);
    QMap<int,int> mountSumNumMap;
    QMap<int,QMap<QString,int>> mountNumMap;
    for (auto &it:m_currNameInfos) {
   
   
        mountSumNumMap[it.idFA]+=it.equipNum;
        mountNumMap[it.idFA][it.equipId]=it.equipNum;
    }

    for (auto &faId:mountSumNumMap.keys()) {
   
   
        int row=ui->tableWidget->rowCount();
        ui->tableWidget->insertRow(row);
        ui->tableWidget->setItem(row,EMountCol::MountID,new QTableWidgetItem(QString::number(faId)));
        ui->tableWidget->setItem(row,EMountCol::MountSum,new QTableWidgetItem(QString::number(mountSumNumMap[faId])));
        QStringList mountConfig;
        for (auto &equipId:mountNumMap[faId].keys()) {
   
   
            mountConfig.append(QString("%1(%2个)").arg(idToNameMap[equipId].toString()).arg(mountNumMap[faId][equipId]));
        }
        ui->tableWidget->setItem(row,EMountCol::MountConfig,\
                                new QTableWidgetItem(mountConfig.join("+")));
    }
}

void SchemeDialog::updataFoldBtnIcon(bool isFold)
{
   
   
    if(isFold)
        ui->foldBtn->setText("□");
    else
        ui->foldBtn->setText("-");
}

void SchemeDialog::setFoldView(bool isFold)
{
   
   
    ui->groupBox->setVisible(!isFold);
    updataFoldBtnIcon(isFold);
}

void SchemeDialog::on_foldBtn_clicked()
{
   
   
    bool isFold = ui->groupBox->isVisible();
    ui->groupBox->setVisible(!isFold);
    emit isFoldSignal(isFold);
    updataFoldBtnIcon(isFold);
}

源码

Gitee:03ComplexTableWidget

模糊知识点

  1. 通过使用 inline 关键字,我们告诉编译器,在每个源文件中只需要保留一个 cTable 的实例,这样就避免了重定义错误

也理解为

inline关键字的作用类似于函数内联,它告诉编译器可以在多个源文件中共享同一个变量实例。

在infos.h中使用inline定义QVector\ cTable是为了确保在多个源文件中包含该头文件时,对cTable的定义不会引起重定义错误

  1. void QTableView::resizeRowsToContents() 方法可以根据QTableWidgetItem中的文本内容自动调整行高,以确保所有的文本都能够完整显示
  • 当你在单元格中使用QTableWidgetItem时,它会自动计算文本的大小并将其显示在单元格中。
    • 调用resizeRowsToContents()方法后,表格会遍历每一行,并根据每个单元格中的文本内容的大小来自动调整行高。

如果单元格是QWidget,resizeRowsToContents()会根据内容的最小高度自动设置单元格的行高

相关文章
|
1月前
使用 SAPGUI 的 Docking 控件将屏幕划分成若干子区域试读版
使用 SAPGUI 的 Docking 控件将屏幕划分成若干子区域试读版
22 6
使用 SAPGUI 的 Docking 控件将屏幕划分成若干子区域试读版
|
1月前
|
JavaScript
【sgExcelGrid】自定义组件:简单模拟Excel表格拖拽、选中单元格、横行、纵列、拖拽圈选等操作
【sgExcelGrid】自定义组件:简单模拟Excel表格拖拽、选中单元格、横行、纵列、拖拽圈选等操作
【sgExcelGrid】自定义组件:简单模拟Excel表格拖拽、选中单元格、横行、纵列、拖拽圈选等操作
|
1月前
【sgCollapseBtn】自定义组件:底部折叠/展开按钮
【sgCollapseBtn】自定义组件:底部折叠/展开按钮
|
6月前
展开&收起,使用SwiftUI搭建一个侧滑展开页面交互
展开&收起,使用SwiftUI搭建一个侧滑展开页面交互
76 0
单文档的BCG程序,为什么在CMainFrame::OnCreate最后设置工具条的标题,为什么无效?
单文档的BCG程序,为什么在CMainFrame::OnCreate最后设置工具条的标题,为什么无效?
|
10月前
|
存储 Android开发 索引
RecyclerView 折叠/展开功能的实现
最近这一两个周都没有怎么更新 QMUI。因为我一直在搞忙于搞微信读书的讲书界面。沉醉于写 bug 和改 bug 之中。
407 0
ElementUI导航菜单嵌套多级折叠面板的小箭头图标bug
ElementUI导航菜单嵌套多级折叠面板的小箭头图标bug
ElementUI导航菜单嵌套多级折叠面板的小箭头图标bug
|
iOS开发
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图)
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图)
198 0
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图)
|
iOS开发
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图) 【修订版】
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图) 【修订版】
410 0
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图) 【修订版】