效果
要求
一、功能概述
二、功能
三、关系
FATable 表
CREATE TABLE fatable (idFA INTEGER,nameId TEXT,equipId TEXT,equipNum INTEGER);
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);
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));
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);
}
源码
模糊知识点
- 通过使用
inline
关键字,我们告诉编译器,在每个源文件中只需要保留一个cTable
的实例,这样就避免了重定义错误
也理解为
inline
关键字的作用类似于函数内联,它告诉编译器可以在多个源文件中共享同一个变量实例。在infos.h中使用inline定义QVector\<CTable\> cTable是为了确保在多个源文件中包含该头文件时,对cTable的定义不会引起重定义错误
- void QTableView::
resizeRowsToContents()
方法可以根据QTableWidgetItem中的文本内容自动调整行高,以确保所有的文本都能够完整显示
当你在单元格中使用
QTableWidgetItem
时,它会自动计算文本的大小并将其显示在单元格中。
- 调用resizeRowsToContents()方法后,表格会遍历每一行,并根据每个单元格中的文本内容的大小来自动调整行高。
如果单元格是QWidget,resizeRowsToContents()会根据内容的最小高
度自动设置单元格的行高