前言

最近在研究表格时,找不到什么好的例子来研究, 索性模仿一下公司开发的软件里的表格案例,做的一个小项目。

效果:

ios tableView 获取当前的cell tablewidget获取当前选择的行_qt

ios tableView 获取当前的cell tablewidget获取当前选择的行_qt_02


其中包括功能:

查找按钮:查找Reference列,符合条件的将其显示出来;不符合条件将其隐藏;

取消按钮:清空输入框文本,显示所有表格项;

插入行按钮:在选中行的下方进行插入一行;

删除行按钮:将选中的表格项进行删除;

首行插入按钮:在首行插入一行记录;

右键菜单跳过点:在SK项打勾✔;

右键菜单取消跳过点:取消行SK项打勾✔。

ui界面

ios tableView 获取当前的cell tablewidget获取当前选择的行_Qt_03


很简单的一个界面,一个lineEdit,五个QPushButton,一个QTableWidget。


撸代码

知识点汇总

设置行数
ui.tableWidget->setRowCount(5);

设置列数
ui.tableWidget->setColumnCount(16);

设置隔行变色
ui.tableWidget->setAlternatingRowColors(true);

设置选择模式
ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectItems); QAbstractItemView::SelectItems 选中一个单元格
QAbstractItemView::SelectRows 选中一行
QAbstractItemView::SelectColumns 选中一列
// 使用此方法也可以设置,更多参数查看qt帮助文档
ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);

设置列表头

  1. 初始化列表头
    QTableWidgetItem *headItem = new QTableWidgetItem;
  2. 获取表头字体并设置字体
    // 获取表头原有字体
    QFont font = headItem->font();font.setBold(true); // 设置粗体
    font.setPointSize(10); // 设置字体大小
    headItem->setFont(font); // 设置字体
  3. 设置列宽与设置行高
    ui.tableWidget->setColumnWidth(5, 50);ui.tableWidget->setRowHeight(5, 30);
  4. 设置列表头文本
    headItem->setText("字符串");
  5. 设置列表头
    ui.tableWidget->setHorizontalHeaderItem(5, headItem);

设置列表头与行行头不可点击
ui.tableWidget->horizontalHeader()->setSectionsClickable(false); horizontalHeader()->setSectionsClickable(false); //水平方向的头不可点击
verticalHeader()->setSectionsClickable(false); //垂直方向的头不可点击

设置固定列宽
ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);设置固定行高
ui.tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);

统一设置表头文本,参数是QStringList类型
ui.tableWidget->setHorizontalHeaderLabels(*this->headText);

隐藏列表头
ui.tableWidget->verticalHeader()->setVisible(false); 隐藏行表头
ui.tableWidget->horizontalHeader()->setVisible(false);

设置行表头背景颜色样式为浅黄色
ui.tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:#ffff9b;}");设置列表头背景颜色样式为浅蓝色
ui.tableWidget->verticalHeader()->setStyleSheet("QHeaderView::section{background:#a7fffa;}");设置左上角两个表头相交的区域的颜色样式为浅灰色
ui.tableWidget->setStyleSheet("QTableCornerButton::section{background:#c2c2c2;}"); 打开ps,选择自己喜欢的颜色,复制颜色编号替换即可。

设置左上角航行于列交汇处的按钮

  1. 获取到左上角行和列交汇处的按钮对象
    QAbstractButton* btn = findChild<QAbstractButton*>();
  2. 连接信号与槽
    链接后,就可以在槽函数中执行自己项目需要的操作。
connect(btn, &QAbstractButton::clicked,
[=]() {
	// 槽函数中执行项目需要的操作
});

设置表格全选
ui.tableWidget->selectAll();

获取的所有选中的单元格
QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems();取消选中所有选中的单元格
ui.tableWidget->clearSelection();

获取单元格的选中状态
ui.tableWidget->item(row, column)->isSelected();

获取选中的最后一行的行号
row = ui.tableWidget->currentRow();

设置焦点对准某个单元格
ui.tableWidget->setCurrentItem(item);

设置单元格选中
ui.tableWidget->setItemSelected(item, true);

获取表格中的所有行
int rowCount = ui.tableWidget->rowCount();获取表格中的所有列
int columnCount = ui.tableWidget->columnCount();

获取单元格的行号
int row = ui.tableWidget->item(row, column)->row();获取单元格的列号
int column = ui.tableWidget->item(row, column)->column();

获取某个单元格
QTableWidgetItem *item = ui.tableWidget->item(row, column);获取某个单元格的文本
ui.tableWidget->item(row, column)->text();

隐藏当前行
ui.tableWidget->hideRow(row);显示当前行
ui.tableWidget->showRow(row);

插入一行
ui.tableWidget->insertRow(row);删除一行
ui.tableWidget->removeRow(row); 注意:删除一行之后,后面的所有行都会往前挪,替换掉被删除行的位置

设置行高
ui.tableWidget->setRowHeight(row, 50);

为单元格分配内存
ui.tableWidget->setItem(row, column, new QTableWidgetItem("单元格文本"));

单元格设置复选框
ui.tableWidget->item(row, column)->setCheckState(Qt::CheckState::Unchecked);

单元格添加控件
ui.tableWidget->setCellWidget(row, column, Widget);

控件居中

仅供参考,使用布局进行居中,然后将布局添加到Widget里,最后将Widget添加到单元格中。

注意:此种方式居中的控件,本人不知道如何获得控件的对象!

QCheckBox * checkBox[] = { new QCheckBox, new QCheckBox, new QCheckBox };
	
int column[] { COLUMN_HEAD_INDEX::CS, COLUMN_HEAD_INDEX::SK, 	COLUMN_HEAD_INDEX::FID };
for (int i = 0; i < sizeof(column) / sizeof(column[0]); i++) {
	QWidget *widget = new QWidget;
	QHBoxLayout *hLayout = new QHBoxLayout();
	hLayout->addWidget(checkBox[i]);
		
	hLayout->setMargin(0);
	// 设置水平居中
	hLayout->setAlignment(widget, Qt::AlignCenter);
	// 设置部件周围的左、上、右、下边距
	hLayout->setContentsMargins(10, 0, 10, 0);
	// 添加布局
	widget->setLayout(hLayout);
	// 添加单元格
	ui.tableWidget->setCellWidget(row, column[i], widget);
	
	//QCheckBox *box = qobject_cast<QCheckBox *>(ui.tableWidget->cellWidget(row, column[i]));
	//box->setCheckState(Qt::CheckState::Checked);
	
	//QHBoxLayout *hbLayout = qobject_cast<QHBoxLayout *>(ui.tableWidget->cellWidget(row, column[i]));
	//qobject_cast<QCheckBox *>(hbLayout->widget())->setCheckState(Qt::CheckState::Checked);
}

返回在给定行和列的单元格中显示的小部件
ui.tableWidget->cellWidget(row, column);

设置单元格文本居中
ui.tableWidget->item(row, column)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

设置滚动条

  1. 获取垂直滚动条对象
    QScrollBar *scareen = ui.tableWidget->verticalScrollBar();
  2. 获取水平滚动条对象
    ui.tableWidget->horizontalScrollBar();
  3. 设置滚动条位置为最上方
    scareen->setValue(scareen->minimum());
  4. 设置滚动条位置为最下方
    scareen->setValue(scareen->maximum());

对容器中的数据进行去重

// 存储被选中的所有行
QVector<int> selectedRows;

// 进行排序
std::sort(selectedRows.begin(), selectedRows.end());  
// 去除容器内重复元素
auto it = std::unique(selectedRows.begin(), selectedRows.end());  
selectedRows.erase(it, selectedRows.end());

鼠标旋停提示当前单元格内容

// 鼠标追踪
ui.tabWidget->setMouseTracking(true);
// 鼠标旋停提示当前单元格内容
connect(ui.tabWidget, &QTableWidget::entered,
[=](QModelIndex index) {
	QToolTip::showText(QCursor::pos(), index.data().toString());
});

右键菜单功能

实例化菜单对象
this->menu = new QMenu(this);

定义菜单子项
QAction *addRowAction = new QAction("插入行");

返回一个分隔符
QAction *separator = this->menu->addSeparator();

将QAction项添加到菜单中
this->menu->addAction(addRowAction);this->menu->addAction(separator);

添加子菜单
QMenu *menu1 = new QMenu("填充元件");this->menu->addMenu(menu1);

鼠标单击菜单子项关联信号与槽
connect(addRowAction, SIGNAL(triggered()), this, SLOT(on_addRowBtn_clicked()));

最后添加上鼠标右键事件函数即可

// 右键显示菜单事件
void contextMenuEvent(QContextMenuEvent * event);

// 鼠标右键显示菜单事件
void QTableWidgets::contextMenuEvent(QContextMenuEvent * event) {
	this->menu->normalGeometry();

	// 菜单出现的位置为当前鼠标的位置
	this->menu->exec(QCursor::pos());
}

代码

有详细注释,对照着看应该可以看懂!

可将代码直接拷贝下来运行。

.h文件

#pragma once

#include <QtWidgets/QWidget>
#include "ui_QTableWidgets.h"

#include <QMenu>
#include <QVector>
#include <QCheckBox>


enum COLUMN_HEAD_INDEX {
	No = 0,
	Reference = 1,
	X = 2,
	Y = 3,
	Z = 4,
	R = 5,
	Part = 6, 
	Feeder = 7,
	Nozzle = 8,
	HD = 9,
	CS = 10,
	CY = 11,
	SK = 12,
	AR = 13,
	FID = 14,
	BL = 15,
	COLUMN = 16
};




class QTableWidgets : public QWidget
{
    Q_OBJECT

public:
    QTableWidgets(QWidget *parent = Q_NULLPTR);

private:
	// 初始化表头文本链表
	void initHeadText();
	// 初始化菜单栏
	void initMenu();
	// 查询显示行
	void SelectDataRow();
	// 检查是否选中一整行
	bool checkedSelectedRows();


	// 右键显示菜单事件
	void contextMenuEvent(QContextMenuEvent * event);

	// 插入行与首行插入
	void insertRow(bool flag);

private slots:
	void on_findBtn_clicked();
	void on_cancleBtn_clicked();
	void on_addRowBtn_clicked();
	void on_removeRowBtn_clicked();
	void on_topRowAddBtn_clicked();

	void skipPoints();			// 跳过点
	void cancleSkipPoints();	// 取消跳过点



private:
    Ui::QTableWidgetsClass ui;

	// 头文本
	QStringList *headText;
	// 第一列No.
	int No;
	// 右键菜单
	QMenu *menu;

	QStringList partList;
	QList<QAction *> partAction;
};

.cpp文件

#include "QTableWidgets.h"

#include <QComboBox>
#include <QCheckBox>
#include <iostream>
#include <QMessageBox>
#include <QDebug>
#include <QAction>
#include <QScrollBar>


#define HEAD_HEIGHT 30
#define HEAD_COUNT 16

#pragma execution_character_set("utf-8") // qt支持显示中文

/* QObjectUserData */
//class myQCheckBoxData :public QObjectUserData {
//public:
//	myQCheckBoxData(QCheckBox *checkBox = nullptr) {
//		this->checkBox = checkBox;
//	}
//
//	QCheckBox * getCheckBox() {
//		return this->checkBox;
//	}
//private:
//	QCheckBox *checkBox;
//};
//
//static int index = 0;
//this->checkBox1 = new QCheckBox;
//this->checkBox2 = new QCheckBox;
//this->checkBox3 = new QCheckBox;
// 将对象内存存储
//this->checkBox->setUserData(index++, new myQCheckBoxData(this->checkBox1));
//this->checkBox->setUserData(index++, new myQCheckBoxData(this->checkBox2));
//this->checkBox->setUserData(index++, new myQCheckBoxData(this->checkBox3));
//
//
// 根据索引获取存储中对应的值
//QObjectUserData *cbox = this->checkBox->userData(row * 3);
// 将其转换类型
//myQCheckBoxData *myCheck = (myQCheckBoxData *)dynamic_cast<myQCheckBoxData *>(cbox);
//if (myCheck) {
//	 获取对应的值
//	QCheckBox * box = myCheck->getCheckBox();
//	box->setCheckState(Qt::CheckState::Checked);
//}


QTableWidgets::QTableWidgets(QWidget *parent)
	: QWidget(parent) {
	ui.setupUi(this);

	this->partList << " " << "0805" << "0603" << "0402";
	this->No = 1;
	// 单元格的宽度
	int headWidth[HEAD_COUNT] = { 40, 100, 80, 80, 80, 80, 100, 120, 100, 40, 40, 40, 40, 40, 40, 40 };

	// 搜索框显示提示文本
	ui.inputEdit->setPlaceholderText("Search...");
	

	this->setFixedSize(850, 555);
	initHeadText();
	initMenu();

	// 设置行数
	//ui.tableWidget->setRowCount(1024);
	// 设置列数
	ui.tableWidget->setColumnCount(HEAD_COUNT);
	// 设置隔行变色
	ui.tableWidget->setAlternatingRowColors(true);

	// 设置选择模式
	ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectItems);
	/*QAbstractItemView::SelectItems	选中一个单元格
	QAbstractItemView::SelectRows		选中一行
	QAbstractItemView::SelectColumns	选中一列*/
	// 使用此方法也可以设置,更多参数查看qt帮助文档
	//ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);

	// 根据列数设置表头
	for (int i = 0; i < ui.tableWidget->columnCount(); i++) {
		QTableWidgetItem *headItem = new QTableWidgetItem;
		// 获取表头原有字体
		QFont font = headItem->font();
		font.setBold(true);			// 设置粗体
		font.setPointSize(10);		// 设置字体大小
		headItem->setFont(font);	// 设置字体


		// 设置列宽
		ui.tableWidget->setColumnWidth(i, headWidth[i]);
		// 设置行高
		ui.tableWidget->setRowHeight(i, HEAD_HEIGHT);
		

		// 设置表头文本
		headItem->setText(this->headText->at(i));

		// 设置表头
		ui.tableWidget->setHorizontalHeaderItem(i, headItem);		
	} 


	//horizontalHeader()->setSectionsClickable(false);    //水平方向的头不可点击
	//verticalHeader()->setSectionsClickable(false);      //垂直方向的头不可点击
	ui.tableWidget->horizontalHeader()->setSectionsClickable(false);


	// 设置固定列宽
	//ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
	// 设置固定行高
	ui.tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);

	
	// 统一设置表头文本,参数是QStringList类型
	//ui.tableWidget->setHorizontalHeaderLabels(*this->headText);

	// 隐藏列表头  
	//ui.tableWidget->verticalHeader()->setVisible(false);   
	// 隐藏行表头
	//ui.tableWidget->horizontalHeader()->setVisible(false); 

	// 设置行表头背景颜色样式为浅黄色
	ui.tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:#ffff9b;}");
	// 设置列表头背景颜色样式为浅蓝色
	ui.tableWidget->verticalHeader()->setStyleSheet("QHeaderView::section{background:#a7fffa;}");
	// 设置左上角两个表头相交的区域的颜色样式为浅灰色
	ui.tableWidget->setStyleSheet("QTableCornerButton::section{background:#c2c2c2;}");


	// 获取到左上角行和列交汇处的按钮对象
	QAbstractButton* btn = findChild<QAbstractButton*>();
	
	// 设置表格全选
	connect(btn, &QAbstractButton::clicked,
	[=]() {
		QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems();	// 获取的所有选中的单元格
		// 设置焦点为最后一行的第一个单元格,但是不起作用。反而使焦点对准第0行的上一行
		ui.tableWidget->setCurrentItem(ui.tableWidget->item(ui.tableWidget->rowCount(), 0));

		// 设置表格全选
		ui.tableWidget->selectAll();
		// 设置单元格选中
		//ui.tableWidget->setItemSelected(item, true);
	});


	for (int i = 0; i < 30; i++) {
		on_addRowBtn_clicked();
	}
}


// 初始化表头文本链表
void QTableWidgets::initHeadText() {
	headText = new QStringList;

	headText->append(QString("No."));
	headText->append(QString("Reference"));
	headText->append(QString("X"));
	headText->append(QString("Y"));
	headText->append(QString("Z"));
	headText->append(QString("R"));
	headText->append(QString("Part"));
	headText->append(QString("Feeder"));
	headText->append(QString("Nozzle"));
	headText->append(QString("HD"));
	headText->append(QString("CS"));
	headText->append(QString("CY"));
	headText->append(QString("SK"));
	headText->append(QString("AR"));
	headText->append(QString("FID"));
	headText->append(QString("BL"));
}


// 初始化菜单栏
void QTableWidgets::initMenu() {
	// 实例化菜单对象
	this->menu = new QMenu(this);

	// 定义菜单子项
	QAction *addRowAction = new QAction("插入行");
	QAction *removeRowAction = new QAction("删除行");
	QAction *skipPointsAction = new QAction("跳过点");
	QAction *cancleSkipPointsAction = new QAction("取消跳过点");
	QAction *skipJointBoardAction = new QAction("跳过拼版");
	QAction *fillElementAction = new QAction("填充元件");
	QAction *separator = this->menu->addSeparator();	// 返回一个分隔符

	// 将QAction项添加到菜单中
	this->menu->addAction(addRowAction);
	this->menu->addAction(removeRowAction);
	this->menu->addAction(skipPointsAction);
	this->menu->addAction(cancleSkipPointsAction);
	this->menu->addAction(separator);
	this->menu->addAction(skipJointBoardAction);
	//this->menu->addAction(fillElementAction);

	QMenu *menu1 = new QMenu("填充元件");

	// 实例化子菜单对象,并将其存入链表中
	for each (QString part in this->partList) {
		this->partAction.append(new QAction(part));
	}

	// 将子菜单对象添加到子菜单中
	for (int i = 0; i < this->partList.count(); i++) {
		menu1->addAction(this->partAction.at(i));
	}

	// 子菜单添加到菜单中
	this->menu->addMenu(menu1);


	// 鼠标单击菜单子项关联信号与槽
	connect(addRowAction, SIGNAL(triggered()), this, SLOT(on_addRowBtn_clicked()));
	connect(removeRowAction, SIGNAL(triggered()), this, SLOT(on_removeRowBtn_clicked()));
	connect(skipPointsAction, SIGNAL(triggered()), this, SLOT(skipPoints()));
	connect(cancleSkipPointsAction, SIGNAL(triggered()), this, SLOT(cancleSkipPoints()));

}


// 鼠标右键显示菜单事件
void QTableWidgets::contextMenuEvent(QContextMenuEvent * event) {
	if (!checkedSelectedRows()) {
		//QMessageBox::information(this, "提示", "请选中一整行!");
		return;
	}

	this->menu->normalGeometry();

	// 菜单出现的位置为当前鼠标的位置
	this->menu->exec(QCursor::pos());
}


// 查询按钮
void QTableWidgets::on_findBtn_clicked() {
	SelectDataRow();
}

// 取消按钮
void QTableWidgets::on_cancleBtn_clicked() {
	// 将输入框文本置空
	ui.inputEdit->setText("");

	// 显示所有行
	int row = ui.tableWidget->rowCount();
	for (int i = 0; i < row; i++) {
		ui.tableWidget->showRow(i);
	}
}



// 插入行按钮
void QTableWidgets::on_addRowBtn_clicked() {
	insertRow(true);
}

// 删除行按钮
void QTableWidgets::on_removeRowBtn_clicked() {

	if (!checkedSelectedRows()) {
		QMessageBox::information(this, "提示", "请选中一整行!");
		return;
	}



	/* 删除多行 */	
	// 存储选中行中的第一个单元格
	QList<QTableWidgetItem *> rowItem;
	// 获得所有选中的单元格的行,去掉重复的行
	QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems();	// 获取的所有选中的单元格

	// 提高效率 与 提示
	if (selectedList.count() == 0) return;
	if (QMessageBox::warning(this, "警告", "是否删除选择行?", QMessageBox::Button::Yes | QMessageBox::Button::No) == QMessageBox::Button::No) {
		return;
	}
	
	// 将每行的第一个单元格存储;每次循环完后加上16,索引就指向了下一行的第一个单元格位置
	for (int row = 0; row < selectedList.count(); row += HEAD_COUNT) {
		rowItem.append(selectedList.at(row));	// 将每行的第一个单元格存储
	}


	// 遍历所有选中行的第一项
	for each (QTableWidgetItem *item in rowItem) {
		// 获取该项对应的行
		int row = item->row();

		// 遍历固定的所有列,释放该行每个单元格的同时,释放单元格里的控件
		for (int column = 0; column < HEAD_COUNT; column++) {
			
			if (column == COLUMN_HEAD_INDEX::Part || column == COLUMN_HEAD_INDEX::Feeder || column == COLUMN_HEAD_INDEX::Nozzle || column == COLUMN_HEAD_INDEX::HD) {
				// 获取到单元格中的控件对象
				//QComboBox *box = qobject_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));
				QComboBox *box = (QComboBox *)dynamic_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));
				delete box;	// 释放
			}

			// 释放单元格内存
			delete ui.tableWidget->item(row, column);
		}
		// 删除行
		ui.tableWidget->removeRow(row);
		// 注意:删除一行之后,后面的所有行都会往前挪,替换掉被删除行的位置
	}


	// 排序No.列
	for (int row = 0; row < ui.tableWidget->rowCount(); row++) {
		ui.tableWidget->item(row, 0)->setText(QString("%1").arg(row + 1));
	}

	// 取消所有选中
	ui.tableWidget->clearSelection();

	// No.编号赋值总行号加一(插入数据连续)
	this->No = ui.tableWidget->rowCount() + 1;
}



// 首行插入
void QTableWidgets::on_topRowAddBtn_clicked() {
	insertRow(false);
}


// 查找显示行
void QTableWidgets::SelectDataRow() {

	// 获取输入框中的文本
	QString str = ui.inputEdit->text();

	// 为空则显示所有行
	if (str.isEmpty()) {
		int row = ui.tableWidget->rowCount();
		for (int i = 0; i < row; i++) {
			ui.tableWidget->showRow(i);
		}
		return;
	}


	int rowCount = ui.tableWidget->rowCount();
	//int columnCount = ui.tableWidget->columnCount();
	for (int row = 0; row < rowCount; row++) {
		QString rowData = "";

		 获得一行当中的所有文本
		//for (int column = 0; column < columnCount; column++) {
		//	if (ui.tableWidget->item(row, column)) {
		//		rowData += ui.tableWidget->item(row, column)->text();
		//	}
		//}


		// 获得Reference单元格的文本
		rowData = ui.tableWidget->item(row, COLUMN_HEAD_INDEX::Reference)->text();

		
		if (rowData.isEmpty()) {
			// 隐藏当前行
			ui.tableWidget->hideRow(row);
		} else {
			// 当前行的文本是否与输入框中的文本相等
			if (rowData.contains(str)) {
				// 显示当前行
				ui.tableWidget->showRow(row);

			} else {
				// 隐藏当前行
				ui.tableWidget->hideRow(row);
			}
		}
	}
}

// 检查是否选中一整行
bool QTableWidgets::checkedSelectedRows() {
	// 获取所有选中的单元格
	QList<QTableWidgetItem *> widgetItems = ui.tableWidget->selectedItems();
	
	// 存储被选中的所有行
	QVector<int> selectedRows;

	// 获得所有选中单元格的行
	for each (QTableWidgetItem *item in widgetItems) {
		selectedRows.append(item->row());
	}
	// 进行排序
	std::sort(selectedRows.begin(), selectedRows.end());  
	// 去除容器内重复元素
	auto it = std::unique(selectedRows.begin(), selectedRows.end());  
	selectedRows.erase(it, selectedRows.end());


	// 遍历所有行的单元格,存在有一个单元格没有被选中,则返回false
	bool selectedFlag = true;
	for (int row = 0; row < selectedRows.count(); row++) {		
		for (int column = 0; column < ui.tableWidget->columnCount(); column++) {
			// 检查单元格有没有被选中
			if (ui.tableWidget->item(selectedRows.at(row), column)->isSelected() == false) {
				selectedFlag = false;
				break;
			}
		}

		// 为false,直接返回结果
		if (selectedFlag == false) return  selectedFlag;

	}


	/* 此处为良好BUG :当用于没有选中任何单元格,也会返回true,是为了默认在行末尾连续插入行 */
	return selectedFlag;
}


 // 插入行与首行插入
void QTableWidgets::insertRow(bool flag) {
	int row = 0;	// 所选中的行号


	if (!checkedSelectedRows()) {
		QMessageBox::information(this, "提示", "请选中一整行!");
		return;
	}


	// 真,插入按钮被点击;假首行插入
	if (flag) {
		QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems();	// 获取所有选中的单元格
		// 为真,没有选中单元格
		if (selectedList.isEmpty()) {
			// 行号默认赋值行尾
			row = ui.tableWidget->rowCount();
		} else {
			// 获取选中的最后一行的行号 + 1
			row = ui.tableWidget->currentRow() + 1;

			// 取消选中所有选中的单元格
			ui.tableWidget->clearSelection();
		}
	}
	


	// 插入一行
	ui.tableWidget->insertRow(row);

	// 设置行高
	ui.tableWidget->setRowHeight(row, HEAD_HEIGHT);

	// 为每个单元格分配内存
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::No, new QTableWidgetItem(QString("%1").arg(No)));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Reference, new QTableWidgetItem(QString("%1").arg(No++)));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::X, new QTableWidgetItem("0.000"));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Y, new QTableWidgetItem("0.000"));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Z, new QTableWidgetItem("0.000"));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::R, new QTableWidgetItem("0.000"));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Part, new QTableWidgetItem);
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Feeder, new QTableWidgetItem);
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::Nozzle, new QTableWidgetItem);
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::HD, new QTableWidgetItem);
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::CS, new QTableWidgetItem);
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::CY, new QTableWidgetItem("1"));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::SK, new QTableWidgetItem);
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::AR, new QTableWidgetItem("1"));
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::FID, new QTableWidgetItem);
	ui.tableWidget->setItem(row, COLUMN_HEAD_INDEX::BL, new QTableWidgetItem("0"));

	// 单元格设置复选框
	ui.tableWidget->item(row, COLUMN_HEAD_INDEX::CS)->setCheckState(Qt::CheckState::Unchecked);
	ui.tableWidget->item(row, COLUMN_HEAD_INDEX::SK)->setCheckState(Qt::CheckState::Unchecked);
	ui.tableWidget->item(row, COLUMN_HEAD_INDEX::FID)->setCheckState(Qt::CheckState::Unchecked);
	

	/* 控件居中 */
	//QCheckBox * checkBox[] = { new QCheckBox, new QCheckBox, new QCheckBox };
	//
	//int column[] { COLUMN_HEAD_INDEX::CS, COLUMN_HEAD_INDEX::SK, COLUMN_HEAD_INDEX::FID };
	//for (int i = 0; i < sizeof(column) / sizeof(column[0]); i++) {
	//	QWidget *widget = new QWidget;
	//	QHBoxLayout *hLayout = new QHBoxLayout();
	//	hLayout->addWidget(checkBox[i]);
	//	
	//	hLayout->setMargin(0);
	//	// 设置水平居中
	//	hLayout->setAlignment(widget, Qt::AlignCenter);
	//	// 设置部件周围的左、上、右、下边距
	//	hLayout->setContentsMargins(10, 0, 10, 0);
	//	// 添加布局
	//	widget->setLayout(hLayout);
	//	// 添加单元格
	//	ui.tableWidget->setCellWidget(row, column[i], widget);
	//
	//	//QCheckBox *box = qobject_cast<QCheckBox *>(ui.tableWidget->cellWidget(row, column[i]));
	//	//box->setCheckState(Qt::CheckState::Checked);
	//
	//	//QHBoxLayout *hbLayout = qobject_cast<QHBoxLayout *>(ui.tableWidget->cellWidget(row, column[i]));
	//	//qobject_cast<QCheckBox *>(hbLayout->widget())->setCheckState(Qt::CheckState::Checked);
	//}


	QStringList Part;
	Part << " " << "0805" << "0603" << "0402";
	QStringList Feeder;
	Feeder << "A" << "C0805(2012)" << "R0603(1608)" << "C0402(1005)";
	QStringList Nozzle;
	Nozzle << "A" << "1-1-EMPTY" << "1-2-CN020" << "1-3-CN030" << "1-4-CN040" << "1-5-CN065" << "1-6-CN140" << "1-7-CN220" << "1-8-CN400";
	QStringList HD;
	HD << "1" << "2" << "3" << "4" << "5" << "6";

	QComboBox *comBox[] = { new QComboBox, new QComboBox, new QComboBox, new QComboBox };
	comBox[0]->addItems(Part);
	comBox[1]->addItems(Feeder);
	comBox[2]->addItems(Nozzle);
	comBox[3]->addItems(HD);

	// 单元格添加控件
	ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::Part, comBox[0]);
	ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::Feeder, comBox[1]);
	ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::Nozzle, comBox[2]);
	ui.tableWidget->setCellWidget(row, COLUMN_HEAD_INDEX::HD, comBox[3]);

	/* ui.tableWidget->cellWidget(row, column) 返回在给定行和列的单元格中显示的小部件 */
	QComboBox *comboBox = qobject_cast<QComboBox *>(ui.tableWidget->cellWidget(row, COLUMN_HEAD_INDEX::Part));
	comboBox->setCurrentIndex(2);	// 根据索默认选择显示
	

	/**************************************************************************************/


	// 设置单元格文本居中
	int columnCount = ui.tableWidget->columnCount();
	for (int column = 0; column < columnCount; column++) {
		ui.tableWidget->item(row, column)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
	}


	// 获取垂直滚动条
	QScrollBar *scareen = ui.tableWidget->verticalScrollBar();
	// ui.tableWidget->horizontalScrollBar();
	// 如果是首行插入
	if (row == 0) {
		// 设置滚动条位置为最上方
		scareen->setValue(scareen->minimum());

	// 如果是尾行插入
	} else if (row == ui.tableWidget->rowCount() - 1) {
		// 设置滚动条位置为最下方
		scareen->setValue(scareen->maximum());
	} else {
		// 否则位置不变
		return;
	}
	
}



// 跳过点操作
void QTableWidgets::skipPoints() {

	// 存储选中行中的第一个单元格
	QList<QTableWidgetItem *> rowItem;
	// 获得所有选中的单元格的行
	QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems();	// 获取的所有选中的单元格

		// 提高效率 与 提示
	if (selectedList.count() == 0) return;
	if (QMessageBox::warning(this, "警告", "是否跳过选择行?", QMessageBox::Button::Yes | QMessageBox::Button::No) == QMessageBox::Button::No) {
		return;
	}

	// 将每行的第一个单元格存储;每次循环完后加上16,索引就指向了下一行的第一个单元格位置
	for (int row = 0; row < selectedList.count(); row += HEAD_COUNT) {
		// 去重
		rowItem.append(selectedList.at(row));	// 将每行的第一个单元格存储
	}



	// 效率就提高了
	for each (QTableWidgetItem *item in rowItem) {
		int row = item->row();
		// 设置为选中状态
		ui.tableWidget->item(row, COLUMN_HEAD_INDEX::SK)->setCheckState(Qt::CheckState::Checked);
	}
}



// 取消跳过点
void QTableWidgets::cancleSkipPoints() {
	// 存储选中行中的第一个单元格
	QList<QTableWidgetItem *> rowItem;
	// 获得所有选中的单元格的行
	QList<QTableWidgetItem *> selectedList = ui.tableWidget->selectedItems();	// 获取的所有选中的单元格

	// 提高效率 与 提示
	if (selectedList.count() == 0) return;
	if (QMessageBox::warning(this, "警告", "是否取消跳过选择行?", QMessageBox::Button::Yes | QMessageBox::Button::No) == QMessageBox::Button::No) {
		return;
	}

	// 将每行的第一个单元格存储;每次循环完后加上16,索引就指向了下一行的第一个单元格位置
	for (int row = 0; row < selectedList.count(); row += HEAD_COUNT) {
		// 去重
		rowItem.append(selectedList.at(row));	// 将每行的第一个单元格存储
	}


	// 效率就提高了
	for each (QTableWidgetItem *item in rowItem) {
		int row = item->row();
		ui.tableWidget->item(row, COLUMN_HEAD_INDEX::SK)->setCheckState(Qt::CheckState::Unchecked);
	}
}

总结:
此小项目本人花了两周时间研究完成,其中蕴涵的知识点还是蛮多的,记录下来,供大家参考借鉴。
删除行记得释放控件的内存。

qt的类型转换:

qobject_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));(QComboBox *)dynamic_cast<QComboBox *>(ui.tableWidget->cellWidget(row, column));